Как получается, что перечисление происходит от System.Enum и одновременно является целым числом время?

Edit : Комментарии внизу. Кроме того, это .


Вот что меня смущает. Я понимаю, что если у меня есть такое перечисление ...

enum Animal
{
    Dog,
    Cat
}

... то, что я, по сути, сделал, это определение типа значения с именем Animal с двумя определенными значениями, Собака и Кот . Этот тип является производным от ссылочного типа System.Enum (то, что типы значений обычно не могут делать - по крайней мере, не в C # - но что разрешено в этом случае), и имеет возможность для приведение в / из значений int .

Если бы способ, который я только что описал выше, был верен, то я ожидал бы, что следующий код вызовет исключение InvalidCastException :

public class Program
{
    public static void Main(string[] args)
    {
        // Box it.
        object animal = Animal.Dog;

        // Unbox it. How are these both successful?
        int i = (int)animal;
        Enum e = (Enum)animal;

        // Prints "0".
        Console.WriteLine(i);

        // Prints "Dog".
        Console.WriteLine(e);
    }
}

Обычно вы не можете распаковать тип значения из System.Object как что-либо кроме его точного типа . Итак, как это возможно? Это как если бы тип Animal был int (а не только конвертируемый в int ) и ] является Enum (а не только конвертируемым в Enum ) одновременно. Это множественное наследование? System.Enum каким-то образом наследуется от System.Int32 (чего я не ожидал, что это возможно)?

Edit : Это не может быть ни одним из над. Следующий код убедительно демонстрирует это (я думаю):

object animal = Animal.Dog;

Console.WriteLine(animal is Enum);
Console.WriteLine(animal is int);

Вышеуказанные результаты:

True
False

Как документация MSDN по перечислениям , так и спецификация C # используют термин «базовый тип»; но я не знаю, что это значит, и никогда не слышал, чтобы это использовалось в отношении чего-либо, кроме перечислений. Что на самом деле означает «базовый тип» ?


Итак, это еще один случай , который получает особую обработку со стороны CLR ?

Мои деньги на это. .. но ответ / объяснение было бы неплохо.


Обновление : Damien_The_Unbeliever предоставил ссылку, чтобы правильно ответить на этот вопрос. Объяснение можно найти в Разделе II спецификации CLI, в разделе перечислений:

Для целей привязки (например, для но я не знаю, что это значит, и никогда не слышал, чтобы это использовалось в отношении чего-либо, кроме перечислений. Что на самом деле «базовый тип» означает ?


Итак, это еще один случай , который получает особую обработку со стороны CLR ?

Мои деньги на это. .. но ответ / объяснение было бы неплохо.


Обновление : Damien_The_Unbeliever предоставил ссылку, чтобы правильно ответить на этот вопрос. Объяснение можно найти в Разделе II спецификации CLI, в разделе перечислений:

Для целей привязки (например, для но я не знаю, что это означает, и я никогда не слышал, чтобы это использовалось в отношении чего-либо, кроме перечислений. Что на самом деле «базовый тип» означает ?


Итак, это еще один случай , который получает особую обработку со стороны CLR ?

Мои деньги на это. .. но ответ / объяснение было бы неплохо.


Обновление : Damien_The_Unbeliever предоставил ссылку, чтобы правильно ответить на этот вопрос. Объяснение можно найти в Разделе II спецификации CLI, в разделе перечислений:

Для целей привязки (например, для это еще один случай, который получает особую обработку со стороны CLR ?

Мои деньги на этот случай ... но ответ / объяснение было бы неплохо.


Обновление : Damien_The_Unbeliever предоставил ссылку, чтобы верно ответить на этот вопрос. Объяснение можно найти в Разделе II спецификации CLI, в разделе перечислений:

Для целей привязки (например, для это еще один случай, который получает особую обработку со стороны CLR ?

Мои деньги на этот случай ... но ответ / объяснение было бы неплохо.


Обновление : Damien_The_Unbeliever предоставил ссылку, чтобы верно ответить на этот вопрос. Объяснение можно найти в Разделе II спецификации CLI, в разделе перечислений:

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

Правка (снова?!) : Постойте, вообще-то, я не знаю, правильно ли я прочитал это в первый раз. Возможно, это не на 100% объясняет специализированное поведение распаковки (хотя я оставляю ответ Дэмиена принятым, поскольку он проливает много света на эту проблему). Я продолжу изучать это ...


Другое редактирование : Чувак, тогда ответ yodaj007 бросил меня в еще один цикл. Почему-то перечисление не совсем то же самое, что int ; но int можно присвоить переменной перечисления без приведения ? Ба?

Я думаю, что все это в конечном итоге освещено ответом Ганса , поэтому я принял его. (Извини, Дэмиен! )

41
задан Community 23 May 2017 в 12:34
поделиться