2013-02-10 68 views
6

我正在研究一個有幾種不同類型的陣列的小型項目(例如double[],float[],int[])。爲了驗證/測試/理智的目的,我將這些陣列中的一些打印到控制檯上。所以我有一個看起來像下面的這些多種功能(簡化這個例子 - 假設我只用一維數組處理):爲什麼System.Array不能是類型約束?

void Print(float[] a) // prints an array of floats 
{ 
    for (int i = 0; i < a.Length; i++) 
    { 
     Console.Write(a[i]); 
    } 
} 

void Print(double[] a) // prints an array of doubles 
{ 
    for (int i = 0; i < a.Length; i++) 
    { 
     Console.Write(a[i]); 
    } 
} 

我,在我無窮的智慧,以爲可以減少一些通過簡單地創建這些函數的通用版本來重複代碼。所以我試過這個:

void Print<T>(T t) where T : Array 
{ 
    for (int i = 0; i < t.Length; i++) 
    { 
     Console.Write(t.GetValue(i)); 
    } 
} 

智能感知是不是在抱怨,但是編譯器失敗,一個很有趣的錯誤:

Constraint cannot be special class 'System.Array'

我看過一個解釋(類似於Object或密封類,但都沒有找到多少,除了一個提及on msdn。任何人都可以向我解釋爲什麼這種情況?爲什麼我無法指定類型約束System.Array

PS:雖然輸入了這一點,我意識到,我可以完成我本來想更容易,用一個簡單的功能是這樣的:

void Print(System.Array a) 
{ 
    for (int i = 0; i < a.Length; i++) 
    { 
     Console.Write(a.GetValue(i)); 
    } 
} 

這是爲什麼有在編譯器陣列的特殊規則?

回答

16

適當的語法做你想要的東西是這樣的:

void Print<T>(T[] array) 
{ 
    for (int i = 0; i < array.Length; i++) 
    { 
     Console.Write(array[i]); 
    } 
} 
+1

有意義,但我仍然好奇_why_我不能有一個基類類型約束的'數組'... – vlad 2013-02-10 05:35:41

+0

另外,出於好奇,是不同於使用'Array'類型的參數?如果我使用'Array',有沒有一些拳擊? – vlad 2013-02-10 05:36:13

+1

@vlad沒有裝箱,因爲數組是引用類型,而不是值類型,儘管你不像裝有類型數組那樣裝箱了它。這也不一樣,因爲'Array'也可能是2,3或N維數組,或者索引不是0的數組。 – Servy 2013-02-10 05:38:58

1

如果從字面上看問題,這將是沒用的,有一個Array約束。它與ValueType約束無關,因爲它實際上不檢查是否使用值類型作爲通用參數,而是您傳遞的類型是否可指定爲ValueType
所以你甚至可以通過Array作爲通用的參數,這是可以的。

什麼是真正有用的是有一個陣列 contraint允許任何類型從Array派生,而不是Array本身:

void Print<TArr>(TArr t) where TArr : array //or [*] or other fancy syntax 

哪裏T可以[][,][,,][,,,],等等上。唯一的非泛型Array參數是我們知道數組的元素類型。

解決這個另一種方法是創建一個自定義Array<T>類的T[]隱含的運算符重載,T[,]T[,,]

編輯:
沒有辦法,即使在CIL(目前)來實現這一點,因爲int[,]Array在任何接口或構造函數中都沒有區別。我們需要where T : Array but not Array itself限制。

+0

這不會是無用的。如果不是禁止,可以寫一個'CopyAndReverseArraySegment (T dest,T source,int start,int length),其中T:System.Array'並讓它接受調用,其中源或目的地之一或兩者都是' System.Array',但仍然拒絕其中'source'和'dest'是不兼容陣列類型的調用。事實上,我不相信有一種方法可以讓'System.Array'作爲一個參數的特定類型,而沒有任何類型的派生類型也被認爲是可以接受的。 – supercat 2015-04-30 15:51:35

相關問題