2010-02-09 96 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) 
    { 
    } 
} 
相關問題