2010-02-09 137 views
76

我是C#的新手,不明白为什么下面的代码不起作用。帮助C#泛型错误 - “类型'T'必须是非空值类型”

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”必须是为了在通用类型或方法“系统使用它作为参数“T”的非空值类型.Nullable <牛逼>“
+1

编译器错误为您提供了函数定义的行,因为这是错误所在。 – SLaks 2010-02-09 16:31:17

回答

144

您需要添加一个T:结构约束:

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>无效。

4

您的通用方法正在使用一个Nullable<T>

但是,您不限制T的类型,因此最终可能是Nullable<Form>,这显然是无效的。

您需要将约束更改为where T : struct, IComparable以确保T只能是值类型。

11

Nullable<T>类型有一个约束,它需要T是一个值类型(在C#中struct)。这就是为什么编译器告诉你关于Nullable<T>而不是你的函数或该函数的调用站点 - 它是错误根源的Nullable类,所以这实际上更有帮助,如果编译器只是指向你的函数并说“这不对,修理它!” (想象一下,如果CoalesceMax使用了几种泛型,并且违反了其中一个泛型的约束 - 知道哪个泛型的约束被破坏比仅仅知道CoalesceMax中的一个或多个约束被破坏更有用。

解决方法是通过引入相同的约束来使您的T及其T兼容。

public static Nullable<T> CoalesceMax<T>(Nullable<T> a, Nullable<T> b) where T : struct, IComparable{ 
    ... 
} 
1

不完全是一个问题的任择议定书,但因为这是突然出现在谷歌相同的错误消息的第一件事就是:这是通过添加struct约束,必须来之前的所有接口/新的约束条件进行,我必须在我的类定义上添加约束条件,而不是我的方法,例如

public class MyClass<T> where T : struct 
{ 
    public void MyMethod(T? value) 
    { 
    } 
} 
相关问题