Я хочу создать общий класс с членом типа T
. T
может быть классом, классом, допускающим значение NULL, структурой или структурой, допускающей значение NULL. Так что в принципе все что угодно. Это упрощенный пример, показывающий мою проблему:
#nullable enable
class Box<T> {
public T Value { get; }
public Box(T value) {
Value = value;
}
public static Box<T> CreateDefault()
=> new Box<T>(default(T));
}
Из-за использования новой функции #nullable enable
я получаю следующее предупреждение: Program.cs(11,23): warning CS8653: A default expression introduces a null value when 'T' is a non-nullable reference type.
Это предупреждение имеет для меня смысл. Затем я попытался исправить это, добавив ?
к параметру свойства и конструктора:
#nullable enable
class Box<T> {
public T? Value { get; }
public Box(T? value) {
Value = value;
}
public static Box<T> CreateDefault()
=> new Box<T>(default(T));
}
Но теперь вместо этого я получаю две ошибки:
Program.cs(4,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint.
Program.cs(6,16): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint.
Однако я не хочу добавлять ограничение. Меня не волнует, является ли T
классом или структурой.
Очевидное решение - заключить нарушителей в директиву #nullable disable
. Однако, как и #pragma warning disable
, я бы не стал этого делать, если в этом нет необходимости. Есть ли другой способ заставить мой код скомпилироваться без отключения проверки допустимости значения NULL или предупреждения CS8653?
$ dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 3.0.100-preview4-011223
Commit: 118dd862c8
T?
для типа значения и ссылочного типа просто не обрабатываются компилятором. Почему? Я мог предположить, что это просто добавило бы много сложности, но я также предполагаю, что вам понадобится ввод от настоящих разработчиков компилятора, чтобы знать наверняка.T?
для типа значения обрабатываетсяNullable<T>
, тогда какT?
для ссылочного типа в C # 8 обрабатываетсяT
с атрибутом. В принципе, я думаю, что это просто не поддерживается. - person Lasse V. Karlsen   schedule 03.05.2019null
переменной типаT
(когдаT
является ссылочным типом), затем вы используетеdefault(T)
, который может b> вернутьnull
для ссылочных типов. Здесь нет никакой загадки. Ты должен выбрать путь, как Нео ... :-) - person JuanR   schedule 03.05.2019T?
действительно разрешаетnull
, проблема здесь в том, что компилятор явно требует, чтобы код был явным относительно того, является лиT
ссылочным типом или типом значения, потому что скомпилированный код будет отличаться для обоих. - person Lasse V. Karlsen   schedule 03.05.2019Box<T> where T : class
вместе сValueBox<T> where T : struct
. Я не думаю, что на данный момент существует способ унифицировать общие типы / методы надT?
иNullable<T>
. - person Jonathon Chase   schedule 03.05.2019default
, но что еще является подходящимdefault
для ссылочных типов? По умолчанию используетсяnull
для ссылочных типов, которые напрямую конфликтуют с использованием ссылочных типов, допускающих значение NULL. Возможно, вам нужно будет ограничитьT
типами, которые могут быть сконструированы по умолчанию (new()
). - person Jeff Mercado   schedule 04.05.2019T? x = y ?? z
, компилятор должен испустить разные инструкции CIL, когда T является типом значения, чем когда это ссылочный тип, но это невозможно, поскольку CLR не t поддерживают существование двух версий метода. Если бы они 15 лет назад решили, что значения NULL, такие какint?
, были просто обычными ссылками (null или значение в рамке), у нас не было бы этой проблемы ... у нас была бы другая - person Qwertie   schedule 18.01.2020