2010-10-05 6 views
2

Compte tenuTuple.Create type de retour

void foo(Tuple<object> t) 
{ 

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

le compilateur C# retourne

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>' 

Ajout de types explicites à Tuple.Create défaites son but. Comment puis-je convaincre le compilateur d'accepter le code? Je pense que

FWIW, C++ n'a pas ce problème: http://live.boost.org/doc/libs/1_33_1/libs/tuple/doc/tuple_users_guide.html#constructing_tuples

+1

Si vous ne vous souciez pas d'être fortement typé, pourquoi ne pas utiliser un fol vide (params object [] args)? – cordialgerm

Répondre

4

C'est le même problème de covariance de type générique qui arrive tous les jours. Il n'est tout simplement pas possible de convertir Foo<T> en Foo<SubT> ou vice versa. À partir de .NET 4, il est pris en charge - mais uniquement pour les interfaces et les délégués, et en spécifiant explicitement le paramètre de type générique comme variant en le déclarant Foo<out T1>.

+0

Et ce n'est pas supporté pour les classes de toute façon; seulement les délégués et les interfaces. – thecoop

+0

@thecoop oups, j'ai oublié ça. Merci –

2

Vous essayez de transformer un Tuple<string> en un Tuple<object>, ce que vous ne pouvez pas faire - la variance générique n'est prise en charge que pour les interfaces et les délégués. Vous devez spécifier explicitement les arguments de type à Tuple.Create:

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

Vous pouvez faire la compilation de code par pas en utilisant Tuple<object> mais en utilisant Tuple<T>

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

Si vous ne voulez pas le faire, vous devez simplement devez être explicite avec la chaîne à objet dans la méthode Tuple.Create.

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

Considérez si vous pourriez avoirTuple<object> et passer ensuite dans un Tuple<string>. Que faire si votre signature était

void(ref Tuple<object> t) 

Il n'y a rien qui vous empêche d'écrire dans cette méthode

t = new Tuple<object>(1); 

Et maintenant, vous avez mis à seulement 1 dans un tuple qui permet uniquement les chaînes. Certes, c'est un cas d'angle car Tuple est intrinsèquement en lecture seule, donc vous avez besoin d'un paramètre ref, mais c'est un cas de problème, néanmoins.