- Базовый тип, допускающий значение NULL, в штучной упаковке можно преобразовать в перечисление, но тип перечисления в штучной упаковке нельзя преобразовать в тип, допускающий значение NULL.
И аналогично,
- Упакованное перечисление, допускающее значение NULL, может быть преобразовано к базовому типу, но упакованное базовый тип не может быть преобразовано в перечисление, допускающее значение NULL.
Хорошо, я знаю, что "упакованный в коробку тип, допускающий значение NULL" - не лучший способ описать это, но это просто вопрос. Я знаю, что это основной тип значения, который попадает в рамку.
Я покажу это на примерах. Предположим, у меня есть enum
с int
в качестве базового типа.
enum Sex { Male, Female }
Случай I:
int? i = 1;
object o = i;
Sex e = (Sex)o; //success
//but
Sex e = Sex.Male;
object o = e;
int? i = (int?)o; //invalid cast
Случай II:
Sex? e = Sex.Male;
object o = e;
int i = (int)o; //success
//but
int i = 1;
object o = i;
Sex? e = (Sex?)o; //invalid cast
В двух словах:
(enum)int? -> succeeds
(int?)enum -> the reverse fails
(int)enum? -> succeeds
(enum?)int -> the reverse fails
Или, говоря еще проще,
преобразование в значение, не допускающее значения NULL -> успешно
преобразование в значение, допускающее значение NULL -> не выполняется
Теперь я точно знаю, что после того, как вы поместите в коробку тип значения, его можно будет вернуть только к исходному типу. Но поскольку по правилам C # упакованный int
может быть преобразован в enum
, а упакованный enum
может быть преобразован в int
, а упакованный int
в int?
и упакованный int?
в int
, я искал последовательного понимания других также сценарии, то есть перечисленные выше. Но я не понимаю логики. Во-первых, я считаю, что если все они потерпели неудачу или все преуспели, это имело больше смысла для разработчиков. Во-вторых, даже успешные забросы выглядят немного странно. Я имею в виду, поскольку тип значения может быть неявно приведен к его эквиваленту, допускающему значение NULL (а не наоборот), приведение к типу, допускающему значение NULL, в любом случае должно быть успешным, но с текущей реализацией тип, допускающий значение NULL, успешно преобразуется в не допускающий значение NULL, что может даже завершиться ошибкой, если первое имело нулевое значение. Если бы все было наоборот, это было бы легче понять. Пример вроде:
Sex? e = null;
object o = e;
int i = (int)o; //succeeds, but sure to explode on cast
//but
int i = 1;
object o = i;
Sex? e = (Sex?)o; //invalid cast, even though its always a safe cast
Вопросы:
Итак, какое правило C # позволяет этому случиться?
Есть ли простой способ запомнить это?
int[]
иuint[]
. - person Jon Skeet   schedule 18.12.2013