Как преобразовать List <interface> в List <concrete>?
У меня есть интерфейс, определяемый как:
public interface MyInterface {
object foo { get; set; };
}
и класс, реализующий этот интерфейс:
public class MyClass : MyInterface {
object foo { get; set; }
}
Затем я создаю функцию, которая возвращает ICollection следующим образом:
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;
}
Он скомпилировал бы, но выбрал бы
Невозможно запустить объект типа 'System.Collections.Generic.List 1[MyInterface]'
to type
'System.Collections.Generic.IEnumerable
1 [МойКласс]'.
исключение. Что я делаю неправильно?
Ответы
Ответ 1
A List<MyInterface>
не может быть преобразован в List<MyClass>
вообще, потому что в первом списке могут быть объекты, реализующие MyInterface
, но не являющиеся фактически объектами типа MyClass
.
Однако, поскольку в вашем случае вы знаете, как вы создали список, и можете быть уверены, что он содержит только объекты MyClass
, вы можете сделать это с помощью Linq:
return list.ConvertAll(o => (MyClass)o);
Ответ 2
Но a List<MyInterface>
категорически не является List<MyClass>
.
Думай:
interface IAnimal { }
class Cat : IAnimal { }
class Dog : IAnimal { }
var list = new List<IAnimal> { new Cat(), new Dog() };
Тогда
var cats = (List<Cat>)list;
Абсурд!
Кроме того,
var cats = list.Cast<Cat>();
Абсурд!
Далее
var cats = list.ConvertAll(x => (Cat)x);
Абсурд!
Вместо этого вы можете сказать
var cats = list.OfType<Cat>();
Ответ 3
Я нахожу Automapper очень полезным для преобразования интерфейсов в конкретные классы.