我是 C# 新手,不明白为什么下面的代码不起作用。
public static Nullable<T> CoalesceMax<T>(Nullable<T> a, Nullable<T> b) where T : IComparable
{
if (a.HasValue && b.HasValue)
return a.Value.CompareTo(b.Value) < 0 ? b : a;
else if (a.HasValue)
return a;
else
return b;
}
// Sample usage:
public DateTime? CalculateDate(DataRow row)
{
DateTime? result = null;
if (!(row["EXPIRATION_DATE"] is DBNull))
result = DateTime.Parse((string)row["EXPIRATION_DATE"]);
if (!(row["SHIPPING_DATE"] is DBNull))
result = CoalesceMax(
result
DateTime.Parse((string)row["SHIPPING_DATE"]).AddYears(1));
// etc.
return result;
}
它在编译期间给出以下错误:
类型“T”必须是不可为空的值类型,才能将其用作泛型类型或方法“System.Nullable
您需要添加一个 T : struct
约束:
public static Nullable<T> CoalesceMax<T>
(Nullable<T> a, Nullable<T> b) where T : struct, IComparable
否则 C# 将尝试找出 Nullable<T>
的含义,并意识到它还没有 Nullable<T>
本身所需的约束。换句话说,您可以尝试调用:
CoalesceMax<string>(...)
这没有意义,因为 Nullable<string>
无效。
Nullable<T>
类型有一个约束,要求 T
是值类型(C# 中的 struct
)。这就是为什么编译器会告诉您有关 Nullable<T>
而不是您的函数或该函数的调用站点的原因 - 它是 Nullable
类是错误的根本原因,所以这实际上更有帮助,如果编译器只是指着你的功能说“这不对,修复它!” (想象一下,如果 CoalesceMax
使用了几个泛型,并且只违反了其中一个的约束 - 知道哪个泛型的约束被破坏比只知道 CoalesceMax
中的一个或多个约束被破坏更有用)。
解决方案是通过引入相同的约束来使您的 T
和它们的 T
兼容。这是通过添加 struct
约束来完成的,该约束必须位于所有接口/新约束之前:
public static Nullable<T> CoalesceMax<T>(Nullable<T> a, Nullable<T> b) where T : struct, IComparable{
...
}
您的通用方法正在使用 Nullable<T>
。
但是,您没有限制 T
的类型,因此它最终可能是 Nullable<Form>
,这显然是无效的。
您需要将约束更改为 where T : struct, IComparable
以确保 T
只能是值类型。
不完全是对 OP 的回答,但由于这是在谷歌上弹出相同错误消息的第一件事,我不得不在我的类定义上添加约束,而不是我的方法,例如
public class MyClass<T> where T : struct
{
public void MyMethod(T? value)
{
}
}
Nullable<T>
仍然需要T
是不可为空的值类型,而不仅仅是任何不可为空的类型。