web-dev-qa-db-fra.com

Liste de diffusion <T> à la liste <Interface>

public interface IDic
{
    int Id { get; set; }
    string Name { get; set; }
}
public class Client : IDic
{

}

Comment puis-je lancer List<Client> à List<IDic>?

96
Andrew Kalashnikov

Vous ne pouvez pas transtyper (en préservant l'identité de référence), ce qui serait dangereux. Par exemple:

public interface IFruit {}

public class Apple : IFruit {}
public class Banana : IFruit {}

...

List<Apple> apples = new List<Apple>();
List<IFruit> fruit = apples; // Fortunately not allowed
fruit.Add(new Banana());

// Eek - it's a banana!
Apple apple = apples[0];

Maintenant, vous pouvez convertir un List<Apple> à un IEnumerable<IFruit> dans .NET 4/C # 4 en raison de la covariance, mais si vous voulez un List<IFruit> vous devez créer une nouvelle liste . Par exemple:

// In .NET 4, using the covariance of IEnumerable<T>
List<IFruit> fruit = apples.ToList<IFruit>();

// In .NET 3.5
List<IFruit> fruit = apples.Cast<IFruit>().ToList();

Mais ceci est pas identique à la distribution de la liste originale - car il y a maintenant deux séparés listes. Ceci est sûr, mais vous devez comprendre que les modifications apportées à une liste ne seront pas visibles dans l'autre liste. (Les modifications apportées aux objets auxquels les listes se réfèrent seront bien sûr visibles).

220
Jon Skeet

Un itérateur de Cast et .ToList ():

List<IDic> casted = input.Cast<IDic>().ToList() fera l'affaire.

A l'origine, j'avais dit que la covariance fonctionnerait - mais comme Jon l'a justement souligné; non ça ne va pas!

Et à l'origine, j'ai aussi bêtement laissé l'appel ToList()

5
Andras Zoltan

Moi aussi j'ai eu ce problème et après avoir lu la réponse de Jon Skeet, j'ai modifié mon code en utilisant List<T> utiliser IEnumerable<T>. Bien que cela ne réponde pas à la question initiale de OP - Comment puis-je lancer List<Client> à List<IDic>, cela évite de le faire et peut donc être utile aux autres personnes confrontées à ce problème. Bien entendu, cela suppose que le code nécessitant l’utilisation de List<IDic> est sous votre contrôle.

Par exemple.:

public void ProcessIDic(IEnumerable<IDic> sequence)
{
   // Implementation
}

Au lieu de:

public void ProcessIDic(List<IDic> list)
{
   // Implementation
}
4
Ɖiamond ǤeezeƦ
List<Client> listOfA = new List<Client>();
List<IDic> list = listOfA.Cast<IDic>().ToList();
2
Marc Messing

Si vous pouvez utiliser LINQ, vous pouvez le faire ...

List<Client> clientList = new List<Client>();
List<IDic> list = clientList.Select(c => (IDic)c).ToList();
2
musefan

Dans .Net 3.5, vous pouvez effectuer les opérations suivantes:

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

Dans ce cas, le constructeur de List prend un IEnumerable.
liste bien que ne soit convertible qu’en IEnumerable. Même si myObj peut être converti en ISomeInterface, le type IEnumerable n'est pas convertible en IEnumerable.

0
Kent Aguilar

Ce n'est possible qu'en créant un nouveau List<IDic> et transférer tous les éléments.

0
Piotr Auguscik