2010-10-05 73 views
2

鑑於Tuple.Create返回類型

void foo(Tuple<object> t) 
{ 

} 
void bar() 
{ 
    foo(Tuple.Create("hello")); 
} 

C#編譯器返回

error CS1502: The best overloaded method match for 'foo(System.Tuple<object>)' has some invalid arguments 
error CS1503: Argument 1: cannot convert from 'System.Tuple<string>' to 'System.Tuple<object>' 

添加明確的類型Tuple.Create違背了它的目的。我如何說服編譯器接受代碼?

FWIW,我認爲C++不存在這個問題:http://live.boost.org/doc/libs/1_33_1/libs/tuple/doc/tuple_users_guide.html#constructing_tuples

+1

如果你不在乎被強類型化爲什麼不使用void foo(params object [] args)? – cordialgerm 2010-10-05 21:55:13

回答

4

這是每天出現的相同泛型類型的協方差問題。根本不可能將Foo<T>轉換爲Foo<SubT>,反之亦然。從.NET 4開始,它支持 - 但僅限於接口和委託,並且通過聲明Foo<out T1>明確指定泛型類型參數作爲變體。

+0

反正它不支持類;只有代表和接口。 – thecoop 2010-10-05 21:59:54

+0

@thecoop哎呀,忘了那一點。謝謝 – 2010-10-05 22:02:39

2

您正試圖將Tuple<string>轉換爲Tuple<object>,您無法這麼做 - 通用差異僅支持接口和委託。您需要顯式地指定類型參數的Tuple.Create

void bar() 
{ 
    foo(Tuple.Create<object>("hello")); 
} 
4

您可以通過使用Tuple<object>,但使用Tuple<T>

void foo<T>(Tuple<T> t) 

如果你不想這樣做,使代碼編譯,你只需要就可以將顯式的帶到Tuple.Create方法的對象中。

Tuple.Create<object>("Hello"); 
Tuple.Create((object)"Hello"); 

考慮,如果你能Tuple<object>然後通過在Tuple<string>。如果你的簽名是

void(ref Tuple<object> t) 

沒有什麼阻止你在那個方法

t = new Tuple<object>(1); 

寫現在你剛剛把1元組中,只允許字符串。當然,這是Tuple本質上只讀的角落案例,所以你需要一個ref參數,但它仍是一個問題。