2010-01-04 5 views
11

si j'ai objectA qui implémente ISomeInterfaceListe des objets à la liste des interfaces

pourquoi je ne peux pas le faire:

List<objectA> list = (some list of objectAs . . .) 

List<ISomeInterface> interfaceList = new List<ISomeInterface>(list); 

pourquoi je ne peux pas tenir dans la liste dans le constructeur interfaceList? Y a-t-il une solution de contournement?

Répondre

23

en C# 3.0 + .Net 3.5 et plus vous pouvez résoudre ce problème en procédant comme suit

List<ISomeInterface> interfaceList = new List<ISomeInterface>(list.Cast<ISomeInterface>()); 

la raison pour laquelle cela ne fonctionne pas est que le constructeur de List<ISomeInterface> dans ce cas, prend une IEnumerable<ISomeInterface>. Le type de la variable de liste n'est cependant convertible qu'en IEnumerable<objectA>. Même si objectA peut être convertible en ISomeInterface, le type IEnumerable<objectA> n'est pas convertible en IEnumerable<ISomeInterface>.

Cela change cependant dans C# 4.0 qui ajoute le support Co et Contravariance au langage et permet de telles conversions.

+1

@itowlson, c'est ce que fait l'utilisateur dans l'échantillon. Ils n'ont pas spécifié le comportement d'ajout faisait partie de la solution souhaitée. – JaredPar

+1

Vous voulez dire .NET 3.5, pas C# 3.5. –

1

Ceci est traité en C# 4.0, vous ne pouvez pas le faire directement en C# 3.5. Vous pouvez créer une nouvelle liste à partir de cette liste et utiliser un opérateur d'extension ou foreach pour le faire proprement, quoique plus lentement qu'un cast au type qui sera fourni par covariance contravariance (toujours se tromper) en C# 4.

+1

Voir mon commentaire à Jared - Il n'y a pas de C# 3.5. –

+0

Arg, me fait penser au beauracrat de Futurama. Bien que ce Linq ait été un changement de langage, et n'a pas été introduit jusqu'à C# 3.5, donc C# était de 2.0 jusqu'à ce qu'il reçoive les extensions linq, WCF était simplement une mise à niveau du framework en 3.0. – Spence

3

& plus court chemin le plus facile est:

var interfaceList = list.Cast<ISomeInterface>().ToList() 

OU

List<ISomeInterface> interfaceList = list.Cast<ISomeInterface>().ToList() 

Les deux ci-dessus des exemples de code sont égaux et vous pouvez utiliser chacun que vous voulez ...

+0

Le bon côté avec l'utilisation de ToList() est une bonne idée! Mais notez qu'en utilisant var vous cachez le type réel de la variable et ce n'est pas une bonne pratique de le faire. Liste interfaceList = liste.Cast (). ToList(); donc je suis allé à utiliser cette forme comme la plus claire, la plus courte version –

+0

@ KovácsEde, selon le point que vous avez mentionné, j'ai ajouté le deuxième format de mon chemin à cette réponse, mais les deux sont égaux. Quand nous utilisons 'var', en fait nous écrivons nos codes dans un format plus court et nous pouvons toujours reconnaître le type de la variable en regardant le côté droit de' = '. D'un autre côté, même lorsque nous utilisons 'var', le compilateur' C# 'est suffisamment cleaver pour reconnaître le type réel de la variable. Donc, si vous voulez une syntaxe plus courte, utilisez 'var' et reconnaissez le type de variable à partir des codes du côté droit de' = 'sinon, vous pouvez utiliser le second format. – RAM

Questions connexes