如何将泛型类型参数约束为仅接受C#中的可空值类型?

时间:2017-03-26 02:27:30

标签: c# syntax nullable value-type generic-constraints

where T : struct约束允许人们将可接受类型参数的域限制为值类型集(与包括值和引用类型的类型的超集相比),但似乎也禁止可以为空的类型虽然nullable并不一定意味着现代版本的C#中的引用类型。

如果我想接受添加了int?DateTime?等可空性的值类型,同时拒绝本机可以为空的引用类型(如字符串,IList等),该怎么办?是否可以通过这种方式定义约束?怎么回事?

我实际上很想学会实现这两个场景:当用作参数的类型必须是值和可空时以及可接受的可空值类型时,以及不可为空的值类型和我仔细考虑这些相关的原因可以借口提及两者,所以我很欣赏关于第二种情况的谦虚评论,并选择一个答案,包括它作为一个更好的答案(如果有更多,另一个在其他方面不会更好)我将提交一个答案,而且我必须选择,但我现在真正需要的是第一种情况(总是需要一个可以为空的类型,同时又是一个值类型)我也是相信第二种情况在第一种情况下会非常直截了当,更不用说坚持将2个问题粘合在一起并不是一种好的方式所以我绝对会欣赏并接受只处理第一种情况的答案。

2 个答案:

答案 0 :(得分:2)

你不能。 Nullable<T>对于C#中的泛型不是有效约束。

当您尝试class X<T,U> where T : Nullable<U>之类的内容时,会出现以下错误:

  

&#39; U&#39?;不是有效的约束。用作约束的类型必须是接口,非密封类或类型参数。

如果您需要同时接受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 :(得分:2)

它不是完全你想要什么,但也许你可以使用IConvertible的类型约束?作为接口,它是可空的,并由布尔,SByte,Byte,Int16,UInt16,Int32,UInt32,Int64,UInt64,Single,Double,Decimal,DateTime,Char和String实现。

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