如何在 C# 中将泛型类型参数限制为仅接受可为 null 的值类型?

How do I constraint a generic type parameter to only accept nullable value types in C#?

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

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

我真的很想学习如何实现这两种情况:当用作参数的类型必须同时是值和可为空时,以及当接受可为空值类型和非可为空值类型时并且我认为这些密切相关以至于可以原谅提及两者所以我很感激对第二种情况的谦虚评论并选择一个答案包括它作为一个更好的答案(假设另一个在其他方面不会真的更好)如果更多比一个答案将被提交,我必须选择,但我现在真正需要的是第一种情况(总是需要一个既可以为 null 又同时是值类型的类型)而且我也相信鉴于第一个案例的知识,第二个案例将非常简单,更不用说坚持将 2 个问题粘在一起不是一个好方法所以我绝对会感激并接受只处理第一个案例的答案。

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

当您尝试类似 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 但在你的 class 中的任何地方都使用 Nullable<T> 作为参数和字段。

关于特定方面的更多讨论 - C# generic type constraint for everything nullable 和相关问题。

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

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