2011-08-17 76 views
12

是否可以在不允許某些類型的泛型類上指定約束?我不知道這是否可能,如果是,我不確定語法是什麼。就像:如何指定.NET泛型約束中不允許的類型?

public class Blah<T> where : !string { 
} 

我似乎無法找到任何允許這種約束的符號。

+0

不認爲這是可能的 - 但爲什麼你會需要這樣的東西? – Carsten

+0

當有人試圖傳入不支持的類型時,期望的行爲是什麼? –

+0

我其實是試圖排除字符串類型,但事實證明,使用T:struct的地方適用於我想要做的事情,因爲我的類無論如何都不適用於複雜類型。 –

回答

11

最接近你可以得到的是一個運行時間約束。

編輯:最初我把運行時檢查放在構造函數調用中。這實際上並不是最佳的,因爲它會在每個實例化上產生開銷;我相信這將是更合理的投入在靜態構造的檢查,這將再次每次用作T參數類型被調用爲您Blah<T>類型:

public class Blah<T> { 
    static Blah() { 
     // This code will only run ONCE per T, rather than every time 
     // you call new Blah<T>() even for valid non-string type Ts 
     if (typeof(T) == typeof(string)) { 
      throw new NotSupportedException("The 'string' type argument is not supported."); 
     } 
    } 
} 

顯然不是理想的,但如果你把這個約束放在文件中,string不是受支持的類型參數(例如,通過XML註釋),您應該得到某處附近編譯時約束的有效性。

+1

通常我將不能用C#表達的約束放入類構造函數中。 – CodesInChaos

+0

要包含可以解析爲字符串的類型:if(typeof(string).IsAssignableFrom(typeof(T)))throw new NotSupportedException – Rasmus

4

不,您不能直接指定「否定」類型約束。

+0

是否有間接方法,其他類似於聲明typeof(T)不是什麼東西? – SirPentor

+0

@SirPentor不是類型約束的一部分,儘管你可以在代碼中做類似的事情。 – Donut

2

限制只能是積極的約束,如documentation中所述。

你能做的唯一的事情就是指定哪些類型可以投入的泛型類型,但不能指定哪些無法被放入其中。

1

下面是允許的約束條件(more detail

  • 其中T:結構
  • 其中T:類
  • 其中T:新的()
  • 其中T:[基類名]
  • 其中T:[接口名稱]
  • 其中T:U(爲T提供的類型參數必須是或爲來自爲U提供的參數)