42 votes

Comment convertir une liste<interface> lister<concrete> ?

J'ai une interface définie comme :

 public interface MyInterface {
     object foo { get; set; };
}

et une classe qui implémente cette interface :

 public class MyClass : MyInterface {
     object foo { get; set; }
}

Je crée ensuite une fonction qui renvoie une ICollection comme ceci :

 public ICollection<MyClass> Classes() {
    List<MyClass> value;

    List<MyInterface> list = new List<MyInterface>(
        new MyInterface[] {
            new MyClass {
                ID = 1
            },
            new MyClass {
                ID = 1
            },
            new MyClass {
                ID = 1
            }
        });

    value = new List<MyClass>((IEnumerable<MyClass>) list);

    return value;
}

Il compilerait mais lancerait un

Impossible de convertir l'objet de type 'System.Collections.Generic.List 1[MyInterface]' to type 'System.Collections.Generic.IEnumerable 1[MyClass]'.

exception. Qu'est-ce que je fais mal?

60voto

JSBձոգչ Points 25069

Un List<MyInterface> ne peut pas être converti en List<MyClass> en général, car la première liste peut contenir des objets qui implémentent MyInterface mais qui ne sont pas réellement des objets de type MyClass .

Cependant, puisque dans votre cas, vous savez comment vous avez construit la liste et pouvez être sûr qu'elle ne contient que des MyClass , vous pouvez le faire en utilisant Linq :

 return list.ConvertAll(o => (MyClass)o);

37voto

Jason Points 125291

Mais un List<MyInterface> n'est absolument pas un List<MyClass> .

Pense:

 interface IAnimal { }

class Cat : IAnimal { }
class Dog : IAnimal { }

var list = new List<IAnimal> { new Cat(), new Dog() };

Puis

 var cats = (List<Cat>)list;

Absurde!

Aussi,

 var cats = list.Cast<Cat>();

Absurde!

Davantage

 var cats = list.ConvertAll(x => (Cat)x);

Absurde!

Au lieu de cela, vous pourriez dire

 var cats = list.OfType<Cat>();

3voto

Minh Nguyen Points 77

Vous pouvez utiliser la méthode d'extension Cast<>

 return list.Cast<MyClass>();

0voto

user925327 Points 63

Je trouve Automapper très utile pour convertir des interfaces en classes concrètes.

0voto

Soheil Points 278

C'est possible et c'est là que brillent les génériques ! Voici un exemple simple :

 public interface ICountable
{
     int Count { get; set; }
}

public class PopularName : ICountable
{
    public string Name { get; set; }
    public int Count { get; set; }
}

public class PopularSize : ICountable
{
     public int Size { get; set; }
     public int Count { get; set; }
}

Et maintenant vous devez déclarer votre méthode (ou votre classe) générique comme ceci :

 public bool HasAnyValue<T>(List<T> countableModel) where T : ICountable
{
    return countableModel.Count > 0;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X