Вопрос

Почему запрещено следующее?

Nullable<Nullable<int>>

тогда как

struct MyNullable <T>
{


}

MyNullable<Nullable<int>> 

не является

Это было полезно?

Решение

Это потому, что ограничение структуры на самом деле означает 'не обнуляемый' поскольку Nullable, несмотря на то, что это структура, имеет значение null (может принимать значение null), Nullable<int> не является допустимым параметром типа для внешнего Nullable.

Это явно выражено в документация по ограничениям

где Т:структура
Аргумент типа должен быть типом значения.Можно указать любой тип значения, кроме Nullable.
Дополнительные сведения см. в разделе Использование типов, допускающих значение NULL (Руководство по программированию на C#).

Если вам нужно обоснование этого, вам потребуются комментарии самого разработчика языка, которых я не могу найти.Однако я бы предположил, что:

  1. изменения в компиляторе и платформе, необходимые для достижения Nullable в его текущей форме, довольно обширны (и были добавлены относительно в последнюю минуту к выпуску 2.0).
  2. У них есть несколько потенциально запутанных крайних случаев.

Разрешение эквивалента int??это только запутало бы, поскольку язык не позволяет отличить Nullable<Nullable<null>> и обнуляемый<null> ни какого-либо очевидного решения следующей проблемы.

Nullable<Nullable<int>> x = null;
Nullable<int> y = null;
Console.WriteLine(x == null); // true
Console.WriteLine(y == null); // true
Console.WriteLine(x == y); // false or a compile time error!

Сделать это возвращение верным было бы очень сложные и значительные накладные расходы на многие операции, связанные с типом Nullable.

Некоторые типы в CLR являются «специальными», примерами являются строки и примитивы, поскольку компилятор и среда выполнения много знают о реализации, используемой друг другом.В этом отношении Nullable также является особенным.Поскольку в других областях это уже специальный корпус, специальный корпус where T : struct аспект не так уж и важен.Преимущество этого заключается в работе со структурами в универсальных классах, поскольку ни одна из них, кроме Nullable, не может сравниваться с null.Это означает, что джит может спокойно рассматривать t == null быть ложным всегда.

Там, где языки спроектированы таким образом, чтобы обеспечить взаимодействие двух очень разных концепций, вы, как правило, получаете странные, запутанные или совершенно опасные крайние случаи.В качестве примера рассмотрим Nullable и операторы равенства.

int? x = null;
int? y = null;
Console.WriteLine(x == y); // true
Console.WriteLine(x >= y); // false!     

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

Что касается точной части спецификации, которая требует этого из раздела 25.7 (выделено мной):

Ограничение типа значения указывает, что аргумент типа, используемый для параметра типа, должен быть типом значения (§25.7.1).Любой не нулевой тип структуры, тип перечисления или параметр типа с ограничением типа значения удовлетворяет этому ограничению.Параметр типа с ограничением типа значения также не должен иметь конструктора-конструктора.Тип System.Nullable определяет ограничение типа значения, не допускающего значения NULL, для T. Таким образом, рекурсивно построенные типы форм T??и обнуляемый<Обнуляемый<Т>> запрещены.

Другие советы

Я считаю, что вы можете использовать только типы значений, не допускающие значения NULL, в Nullableс.С Nullable сам по себе является нулевым, вложение таким образом запрещено.

От http://msdn.microsoft.com/en-us/library/kwxxazwb.aspx

public Nullable(
    T value
)

Тип:T Тип значения.

Nullable является особенным, поскольку в CLR имеется явная поддержка упаковки и распаковки типов Nullable:

Если вы используете MSIL box инструкция против Nullable<T>, вы действительно получите null в результате.Не существует другого типа значения, который при упаковке выдавал бы значение NULL.

Существует аналогичная и симметричная поддержка распаковки.

Параметр универсального типа для Nullable сам должен быть типом, не допускающим значение NULL (т.тип значения).Это предупреждение компилятора C#, которое я получаю, и оно, казалось бы, имеет смысл.Скажи мне, почему ты вообще хочешь это сделать?Лично я не вижу никакой пользы и даже особого смысла в таком заявлении.

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

Цитата: MSDN:

Нулевая (T) структура поддерживает только тип значения в качестве нулевого типа, поскольку эталонные типы являются нулевыми по конструкции.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top