2010-06-08 58 views
5

在一個元組中,如果你有超過7個元素,你可以提供一個第8個元素,它是另一個元組並且定義多達7個元素,然後是另一個元組作爲第8個元素,並且在該行上。但是,編譯時對第8項沒有限制。例如,這是編譯器的合法代碼:爲什麼Tuple <T1... TRest>中的TRest不受約束?

var tuple = new Tuple<int, int, int, int, int, int, int, double> 
       (1, 1, 1, 1, 1, 1, 1, 1d); 

即使智能感知文檔說TRest必須是Tuple。編寫或構建代碼時不會出現任何錯誤,它不會在運行時以ArgumentException的形式出現。

你可以大致在幾分鐘內實現一個元組,完成一個元組約束的第8項。我只是想知道爲什麼它離開了當前的實施?它可能是一個向前兼容性問題,他們可以在假設的C#5中添加更多元素?

短版的粗糙實施

interface IMyTuple { } 

class MyTuple<T1> : IMyTuple 
{ 
    public T1 Item1 { get; private set; } 
    public MyTuple(T1 item1) { Item1 = item1; } 
} 

class MyTuple<T1, T2> : MyTuple<T1> 
{ 
    public T2 Item2 { get; private set; } 
    public MyTuple(T1 item1, T2 item2) : base(item1) { Item2 = item2; } 
} 

class MyTuple<T1, T2, TRest> : MyTuple<T1, T2> where TRest : IMyTuple 
{ 
    public TRest Rest { get; private set; } 
    public MyTuple(T1 item1, T2 item2, TRest rest) 
     : base(item1, item2) 
    { 
     Rest = rest; 
    } 
} 

...

var mytuple = new MyTuple<int, int, MyTuple<int>> 
       (1, 1, new MyTuple<int>(1)); // legal 
var mytuple2 = new MyTuple<int, int, int>(1, 2, 3); // illegal at compile time 
+0

真的嗎?如何實現這一點,以便最後一個元素被限制爲任何大小的「Tuple」,而不需要定義在各種通用'Tuple'大小中通用的額外基類或接口?我不明白你認爲他們可以在C#中做到這一點。 – mquander 2010-06-08 01:04:42

+1

@mquander,Tuple實現ITuple。您可以定義自己的Tuple(MyTuple)類型,將最後一項限制爲一個接口(IMyTuple),並且您將獲得編譯時檢查。 – 2010-06-08 01:08:38

+2

哦,我不知道「ITuple」。感謝您的更正。我注意到'ITuple'是內部的;也許他們想保持內在 - 如果這是一個限制,它將不得不公開。 – mquander 2010-06-08 01:09:58

回答

1

假想ITuple約束不會真的限制它是一個元組[1],將它?只是一個實施ITuple的課程。

[1] - 我將「元組」定義爲BCL提供的Tuple<>類之一。

+0

這是一個有趣的觀點。你是對的,任何舊類型都可以實現這個接口(不管是什麼),並滿足約束的要求。但是,我想這也引發了爲什麼在運行時限制類型的問題,你可以將一個Tuple放到任何一個現有的插槽中,只是說「我們正在創建一個8插槽(最大)的泛型類,用它作爲你看起來合適。「 – 2010-06-08 01:58:49

+1

這是真正將它限制爲一個元組的唯一方法(運行時檢查「內部」接口,所以我們不能實現它)。最後一個槽實際上必須是一個元組,因爲它會影響'Size','GetHashCode','ToString'等的實現。它的處理方式與其他槽完全不同。 – 2010-06-08 09:13:00

7

這是一個類型系統的限制。 ITuple是一個內部接口。如果它是一個通用的約束,它將需要公開,然後讓每個人都實現自己的ITuple,這與元組無關。將它限制在內部可以讓BCL團隊保證它實際上是某種元組,但是結果TRest比編譯時安全得多。

相關問題