Руководство по неявному преобразованию .Net - PullRequest
3 голосов
/ 24 декабря 2008

Каковы общие рекомендации относительно того, когда пользовательское неявное преобразование может, должно или не должно быть определено?

Я имею в виду такие вещи, как, например, «неявное преобразование никогда не должно терять информацию», «неявное преобразование никогда не должно вызывать исключения» или «неявное преобразование никогда не должно создавать новые объекты». Я почти уверен, что первый правильный, третий - нет (или мы могли бы когда-либо иметь неявное преобразование в структуры), и я не знаю насчет второго.

Ответы [ 4 ]

14 голосов
/ 24 декабря 2008

Первое не так просто, как вы могли ожидать. Вот пример:

using System;

class Test
{
    static void Main()
    {
        long firstLong = long.MaxValue - 2;
        long secondLong = firstLong - 1;

        double firstDouble = firstLong;
        double secondDouble = secondLong;

        // Prints False as expected
        Console.WriteLine(firstLong == secondLong);

        // Prints True!
        Console.WriteLine(firstDouble == secondDouble);        
    }
}

Лично я очень редко создаю свои собственные неявные преобразования. Я достаточно счастлив с теми, что в рамках, но я редко чувствую, что добавление моего собственного сделает жизнь лучше. (То же самое относится и к типам значений в общем, кстати.)

РЕДАКТИРОВАТЬ: Просто чтобы немного ответить на этот вопрос, вероятно, стоит прочитать часть операторов преобразования руководящих принципов проектирования библиотеки классов Microsoft .

2 голосов
/ 24 декабря 2008

Я бы точно согласился с первым - вторым большую часть времени («никогда не говори никогда»), но третий не был бы взволнован; кроме всего прочего, он создает ненужное различие между структурами и классами. В некоторых случаях наличие неявного преобразования может значительно упростить соглашение о вызовах.

Для явных преобразований возможно все.

Однако не так часто нужно писать операторы преобразования. И во многих случаях явные операторы являются более полезными, принимая, что они могут нарушаться, если условия не верны (например, с Nullable<T>, если они не имеют значения).

1 голос
/ 04 сентября 2013

Если вы будете поддерживать неявные преобразования только среди объектов ваших собственных типов, я бы посоветовал вам решить, какие «аксиомы» следует применять к таким преобразованиям (например, может быть полезно решить, что если a==b, b==c и a==c все являются допустимыми, и два из них являются истинными, третий также должен быть истинным), а затем определить наиболее полезный набор преобразований, который позволил бы сохранить эти аксиомы. Я обсуждаю четыре полезные аксиомы в своем блоге на http://supercatnet.blogspot.com/2013/09/axioms-of-implicit-type-conversion.html (к сожалению, .NET Framework включает преобразования, которые нарушают все четыре, но запрещает преобразования, которые не должны были бы).

Важно учитывать, что неявные преобразования в неточных типов в большинстве случаев представляют меньший риск удивления, чем преобразования из неточных типов, но есть заметное исключение: если что-то более точного типа передается методу или оператору с перегрузками, которые принимают и более точный тип, и менее точный тип, в который оно может быть преобразовано, некоторый уровень «удивительного» поведения будет почти неизбежным если не сделать невозможным неявное преобразование [например, поведение, если программист пишет if (someLong == someFloat), может быть удивительным, но не потому, что потеря точности при неявном преобразовании long в float удивительна, а скорее потому, что существует по крайней мере шесть различных способов сравнения long, а float (*) и any , означающие, что компилятор может присоединиться к прямому сравнению, удивят тех, кто ожидал чего-то другого. Единственное решение, которое я знаю, чтобы избежать такого удивления, состоит в том, чтобы обеспечить перегрузки, чтобы явно охватить все неоднозначные случаи и пометить их тегом [Obsolete()]. Делать это может быть несколько неловко, но это даст существенное преимущество в том, что сможет удовлетворить все четыре аксиомы.

(*) Программист мог бы, вероятно, намереваться проверить, было ли длинное значение равным значению числа с плавающей запятой, округленного до ближайшего, усеченного до нуля или обнуленного до отрицательной бесконечности; альтернативно, программист может захотеть проверить, был ли float тот, который представляет long, имеют ли float и long одинаковое номинальное значение или float и long оба преобразуются в одно и то же double.

0 голосов
/ 24 декабря 2008

Пограничный случай, который заставил меня задать этот вопрос, является нарушением второго. А именно, у меня есть класс Lazy (не все?), И я начал размышлять о том, не следует ли мне предоставить неявное преобразование в T. Мой инстинкт говорит: да, а текущая версия делает, но я не слишком точно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...