2017-03-26 150 views
1

where T : struct約束允許將可接受類型參數的域限制爲值類型集(與包括值和引用類型的類型的超集相比),但似乎也完全禁止可空類型,儘管可爲空必然意味着現代版本的C#中的引用類型。如何限制泛型類型參數只接受C#中的空值類型?

如果我想要接受像int?DateTime?等增加可空性的值類型,同時拒絕像字符串,IList等本地可空的引用類型,該怎麼辦?這樣可以定義約束嗎?如果是這樣?

我真的很好奇學習如何實現這兩種情況:當用作參數的類型必須是值和可爲空,並且可以接受可爲null的值類型以及不可爲空值類型時,以及我認爲這些相關性足夠緊密,所以不妨提及兩者,所以我會欣賞關於第二種情況的謙遜評論,並選擇一個包括它作爲更好的答案的答案(假如另一個答案在其他方面不會更好),如果超過一個答案將被提交,我將不得不選擇,但我現在實際需要的是第一個案例(總是需要一個既可爲空也是一個值類型的類型),我也相信第二個考慮到第一種情況,情況會非常簡單,更不用說堅持把兩個問題粘合成一個問題是不好的,所以我會將abs對於只處理第一種情況的人,我也會表示理解並接受答案。

+0

你試過使用System.Nullable 作爲約束嗎? https://msdn.microsoft.com/en-us/library/b3h38hb0.aspx – linuxuser27

+1

對C#的不幸通用約束是有限的,沒有人可以提供一個不存在的功能的答案,甚至不是Eric Lippert :) –

+0

@SelmanGençD'oh!那就對了。我一直忘記那個限制。我沒有VS在我面前,所以我可以測試:) – linuxuser27

回答

2

你不能。對於C#中的泛型,Nullable<T>不是有效的約束。

當你嘗試類似class X<T,U> where T : Nullable<U>你得到以下錯誤:

'U?' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter.

如果你需要同時接受TNullable<T>方法參數你可以提供覆蓋:

class X<T> where T : struct 
{ 
    public void R(T arg){ Console.WriteLine("Non nullable: {0}", arg);} 
    public void R(Nullable<T> arg){Console.WriteLine("Nullable: {0}", arg);} 
} 

然後你可以調用以下任一版本:

X<int> r = new X<int>(); 
r.R((int?)4); 
r.R(4); 

在您的類型僅處理Nullable值時,您可以簡單地將約束條件限制爲T:struct,但是班級內部的任何地方都可以使用Nullable<T>作爲參數和字段。

關於特定方面的更多討論 - C# generic type constraint for everything nullable及相關問題。

1

這不是究竟是你想要什麼,但也許你可以使用IConvertible的類型約束?作爲接口,它是可空的,並且通過布爾,SByte,Byte,Int16,UInt16,Int32,UInt32,Int64,UInt64,Single,Double,Decimal,DateTime,Char和String來實現。

class MyClass<T> where T : IConvertible 
{ 
    //Etc 
} 
+0

雖然我不覺得我可以接受這一點,因爲它不是嚴格意義上的答案,請表示我衷心的感謝,感謝一個有趣的貢獻並致詞。 – Ivan