К сожалению, параметры универсального типа не соответствуют тем же правилам набора типов, что и автономные типы.Они ограничены тем, что говорит универсальный тип, что позволяет;это называется ковариация и контравариантность , и в C # только массивы, интерфейсы и делегаты могут быть ковариантными или контравариантными.Конкретные типы, такие как List
, не могут быть (по крайней мере, в C # 4.0).
(Причина, по которой генерики не работают так, как вы думаете в общем , заключается в том, что их невозможно узнатьчто универсальный тип делает с его параметрами типа: ковариация интуитивно понятна, потому что так работают простые присваивания, но во многих случаях нам действительно нужна контрвариантность: поскольку компилятор не может принять решение за нас, он по умолчанию не принимает ни того, ни другого, если вы не скажете иначе.)
Для получения дополнительной информации о со / контравариантности в C # 4 я бы порекомендовал вам ознакомиться с серией сообщений Эрика Липперта об этом, в частности:
http://blogs.msdn.com/b/ericlippert/archive/2009/11/30/what-s-the-difference-between-covariance-and-assignment-compatibility.aspx
и статья MSDN об этом:
http://msdn.microsoft.com/en-us/library/dd799517.aspx
К счастью, в этом случае есть простой ответ, явный метод IEnumerable.Cast
:
Cities = (efCities.Select(o => new City() { Id = o.Id, Country = o.Country,
Province = o.Province, CityName = o.CityName }).Cast<ICity>.ToList());
Другойопция должна использовать IEnumerable<T>
вместо List<T>
.IEnumerable<T>
является ковариантным в T
, поэтому ваше назначение будет работать:
interface IA
{
int Foo();
}
class A : IA
{
public int Foo()
{
return 0;
}
}
public DoStuff()
{
List<A> la = new List<A> { new A(), new A(), new A(), new A() };
// This is an error -- List<A> is not covariant with List<IA>
// List<IA> lia = la;
// This is fine; List<A> implements IEnumerable<A>
IEnumerable<A> iea = la;
// Also fine: IEnumerable<A> is covariant with IEnumerable<IA>
IEnumerable<IA> ieia = la;
}