Почему C # 3 допускает неявное преобразование литерального нуля (0) в любой Enum? - PullRequest
9 голосов
/ 27 октября 2009

C # 3 (Visual Studio 2008) внесло существенное изменение в язык (http://msdn.microsoft.com/en-us/library/cc713578.aspx, см. Изменение 12), позволяющее неявно преобразовывать любой буквенный ноль в Enum. Это кажется странным во многих отношениях. Кто-нибудь знает, почему это часть спецификации? Почему не буквальный? Или семь? Почему ноль особенный? И это делает очень противоречивый выбор разрешения перегрузки. Например.

function string F(object o) { return o.ToString(); }
function string F(DbType t) { return t.ToString(); }
int i = 0;
F((long)0) == "String" // would have been "0" in VS 2005
F(0) == "String"
F(i) == "0"

Очень запутанно и преднамеренно внесено критическое изменение в язык. Есть идеи?

Ответы [ 5 ]

10 голосов
/ 27 октября 2009

C # всегда допускал неявное преобразование литерала 0 в любое значение Enum. Изменилось то, как правило применяется к другим константным выражениям. Это было сделано, чтобы быть более последовательным и позволять любым константным выражениям, которые оцениваются в 0, быть неявно конвертируемыми в перечисление.

Приведенный вами пример демонстрирует одинаковое поведение во всех версиях C #.

Вот пример измененного поведения (непосредственно из связанной документации )

public enum E
{
    Zero = 0,
    One = 1,
} 

class A
{
    public static A(string s, object o)
    { System.Console.WriteLine("{0} => A(object)", s); } 

    public static A(string s, E e)
    { System.Console.WriteLine("{0} => A(Enum E)", s); }

    static void Main()
    {
        A a1 = new A("0", 0);
        A a3 = new A("(int) E.Zero", (int) E.Zero);
    }
}

Вывод Visual C # 2005:

0 => A(Enum E)
(int) E.Zero => A(object)

Вывод Visual C # 2008:

0 => A(Enum E)
(int) E.Zero => A(Enum E)
4 голосов
/ 27 октября 2009

Я думаю, это потому, что 0 считается "значением по умолчанию" для перечислений.

C # (ключевое слово по умолчанию было введено в C # 2.0)

enum DbType {
    Unspecified,
    SqlServer
}

DbType t;
int i = 0;

Console.WriteLine(t == i);
Console.WriteLine(i == default(DbType));

Выходы:

True
True
2 голосов
/ 27 октября 2009

Это было разрешено начиная с версии 1.0. Это значение по умолчанию для перечисления.

"Литерал 0 неявно конвертируем к любому типу перечисления. В Visual C # 2005 и более ранние версии компилятора, Есть также некоторые постоянные выражения, которые оценивают до 0, что может неявно конвертировать в любое перечисление тип, но правило, которое определяет какое из этих выражений кабриолет неясен. В Visual C # 2008, все постоянные выражения, которые равны 0, могут быть неявно преобразован в любой тип перечисления. "

0 голосов
/ 27 октября 2009

Как уже упоминалось, 0 - это перечисление по умолчанию. Попытайтесь думать о перечислениях следующим образом (более явно):

public enum HairColor
{
    Blonde           = 0x0000;
    Brunett          = 0x0001;
    Red              = 0x0002;
    StrawberryBlonde = 0x0004;
}

Поскольку вы не указали явно свои значения данного перечисления, C # автоматически назначит ему значение по умолчанию. Если вы не хотите этого, вам придется явно определять значения для данного перечисления.

0 голосов
/ 27 октября 2009

"Базовым типом по умолчанию для элементов перечисления является int. По умолчанию первый перечислитель имеет значение 0, а значение каждого последующего перечислителя увеличивается на 1." - Это из MSDN заметки для 1.1 Framework , так что всегда было так.

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