[英]generic class using nullable property of generic type
我有以下 class:
class GenericClass<T>
{
public T? A { get; init; }
public T B { get; init; }
public GenericClass(T? a, T b)
{
A = a;
B = b;
}
}
我想將它用於任何類型的T
,無論是struct
、 class
enum
。 我只想確保屬性A
始終可以為 null,而屬性B
的可空性與T
的相同。 但這似乎不起作用。
如果我寫
static void MyTestMethod()
{
var vStruct = new GenericClass<bool>(null, true);
var vNullableStruct = new GenericClass<bool?>(null, true);
var vClass = new GenericClass<string>(null, "hello");
var vNullableClass = new GenericClass<string?>(null, "hello");
var vEnum = new GenericClass<Color>(null, Color.red);
var vNullableEnum = new GenericClass<Color?>(null, Color.red);
}
其中Color
定義為enum Color { red, green, blue }
,
我收到vStruct
和vEnum
:
參數“1”:無法從
<NULL>
轉換為bool
/Color
在這兩種情況下, new GenericClass<...>
的鼠標懸停都顯示 arguments 為不可空,盡管我明確將A
定義為可空。 為什么?
我可以添加一個類型約束: class GenericClass<T> where T: struct
,這將使之前出錯的兩行( vStruct
和vEnum
)沒有錯誤,但會將所有其他行標記為錯誤。 這次出現編譯器錯誤 CS0453:
bool?
/string
/string?
/Color
必須是不可為 null 的值類型,才能將其用作泛型類型或方法GenericClass<T>
中的參數T
這是完全有道理的; 他們不是struct
。
但是如何讓我的GenericClass<T>
同時適用於類和結構/枚舉?
sjb-sjb 在此答案下方的評論提供了我的“為什么”的答案:
實際上,在 C#9 中,T 不受約束(甚至約束為 notnull),語法“T?” 表示“對應於 T 的可默認類型”,而不是“對應於 T 的可空類型”,就像它在語言中的其他地方一樣。 但是,如果您將 T 限制為 class 或結構,則“T?” 再次開始表示“對應於 T 的可空類型”。
感謝 JonasH 的評論,我想出了一個解決方案/解決方法。 我創建了一個自定義的Nullable<T>
類型並從T?
到Nullable<T>
以便我可以在構造GenericClass<...>
時使用與我在問題中使用的語法幾乎相同的語法:
struct Nullable<T>
{
public static Nullable<T> Null => new Nullable<T>(false, default(T)!);
public bool HasValue { get; init; }
private T? _value;
public T Value
{
get => HasValue ? _value
: throw new System.InvalidOperationException("no value present!");
init => _value = value;
}
private Nullable(bool hasValue, T value)
{
HasValue = hasValue;
_value = value;
}
public static implicit operator Nullable<T>(T? n)
=> n == null ? Null : new Nullable<T>(true, n);
}
兩條有問題的線
var vStruct = new GenericClass<bool>(null, true);
var vEnum = new GenericClass<Color>(null, Color.red);
仍然拋出 CS1503,但我可以將它們更改為
var vStruct = new GenericClass<bool>(Nullable<bool>.Null, true);
var vEnum = new GenericClass<Color>(Nullable<Color>.Null, Color.red);
它有效。 我可以對其他行做同樣的事情,但我不需要; 隱式轉換在那里使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.