2013-06-13 65 views
51

我有以下通用方法,但是VS給了我一個編譯錯誤。 (操作員「??」不能應用於類型「T」和「T」的操作數)運營商'??'不能應用於類型'T'和'T'的操作數

public static T Method<T>(T model) where T : new() 
{ 
    var m = model ?? new T(); 
} 

是否有人有任何想法,爲什麼?

編輯︰是否有可能的原因是,T可以是一個結構在我的情況,並且一個結構是一個非空類型?

回答

53

您應該添加class約束:

public static T Method<T>(T model) where T : class, new() 
{ 
    var m = model ?? new T(); 

    return m; 
} 

而且你應該返回m呢!

注:由於@KristofDegrave在他的評論中提到的,我們必須添加class約束的原因是因爲T可以是一個值的類型,比如int和自??運營商(空 - 結合)檢查的類型,可以爲空,所以我們必須添加class約束來排除值類型。

編輯:Alvin Wong的回答涵蓋了可空類型的情況;這實際上是結構,但可以是操作數?運營商。請注意,Method將返回null,但不包含Alvin的重載版本,用於可爲空的類型。

+0

爲什麼他應該'返回m'而不是'返回模型?新的T();'我認爲結果會是一樣的? – WiiMaxx

+2

當然他們是一樣的!但是在第一個問題中使用了這個問題。這只是我提到的。 –

+3

是否有可能的原因是,T可以是一個結構在我的情況,並且一個結構是一個非空類型? –

8

你需要指定你的T類型與在泛型類型約束的類:

public static T Method<T>(T model) where T : class, new() 
{ 
    return model ?? new T(); 
} 
4

由於T可以是任何類型的,沒有保證T將有一個靜態的?運算符或類型T是可空的。

?? Operator (C# Reference)

的??運算符稱爲空合併運算符,用於定義可爲空的值類型的默認值或用於 類型的 定義默認值。

83

??是空合併運算符。它不能應用於非空類型。由於T可以是任何東西,因此它可以是int或其他原始不可爲空的類型。

如果添加條件where T : class(必須在new()之前指定),它將強制T爲可爲空的類實例。

+0

不會將新()條件力T是一個可空類型? –

+3

@KristofDegrave沒有新的()只意味着將有一個空的構造者 – WiiMaxx

+0

是否有可能的原因是T可以是一個結構在我的情況,並且一個結構是一個非空類型? –

0

model ?? new T()表示model == null ? new T() : model。不保證模型不可爲空且==不能應用於null和不可空的對象。改變約束到where T : class, new()應該工作。

0

馬克T爲「班」,你很好去。

4

出於某種原因,??運營商不能在非可空類型中使用,即使它被認爲是相當於model == null ? new T() : model,你允許與非可空類型空比較。

你可以得到你通過使用三元操盤手,或if語句尋找沒有任何額外的限制到底是什麼:

public static T Method<T>(T model) where T : new() 
{ 
    var m = model == null ? new T() : model; 
} 
+0

這不能處理'Nullable <>'類型。當'model'爲'null'時它返回'null'。 –

+1

@AlvinWong那麼'var m = new int?()'應該是'null'。對於值類型,'new T()'類似於(如果不完全相同)'default(T)'。如果你想將可空類型初始化爲默認構造函數的結果以外的內容,那麼這個代碼是不夠的,但這不是OP的問題。 –

31

許多人已經指出添加class約束的通用將解決問題。

如果你希望你的方法適用於Nullable<T>也可以添加過載它:

// For reference types 
public static T Method<T>(T model) where T : class, new() 
{ 
    return model ?? new T(); 
} 

// For Nullable<T> 
public static T Method<T>(T? model) where T : struct 
{ 
    return model ?? new T(); // OR 
    return model ?? default(T); 
} 
+0

Tnx指出,但我不需要支持它的結構值:) –

+10

@KristofDegrave只是指出了完整性。其他人可能需要它! :) –

相關問題