Это не допускается, потому что T
в List<T>
является инвариантом.Вот пример, который объяснит:
public interface IFruit
{
string Name { get; set; }
}
public class Apple : IFruit
{
public string Name { get; set; }
public string Color { get; set; }
}
public class Orange : IFruit
{
public string Name { get; set; }
}
Давайте добавим несколько фруктов в список:
var fruits = new List<IFruit>();
fruits.Add(new Apple());
fruits.Add(new Orange());
Позже в коде вы не знаете, что было добавлено, и вы делаете это:
Orange orange = fruits[0];
Теперь это не скомпилируется, но также не имеет смысла, потому что каждый IFruit
не является Apple
или Orange
.
Что, если компилятор разрешил это?
Если, например, скажем, то, что вы пытаетесь, было разрешено компилятором, например:
// does not compile but let's say it did
List<Apple> fruits = new List<IFruit>();
Тогда, если компилятор разрешил это, он должен также разрешить это, поскольку они оба реализуют IFruit
:
fruits.Add(new Apple());
fruits.Add(new Orange());
, а затем где-нибудь в коде вы делаете это (так как это список яблок)):
foreach (var thisFruit in fruits)
{
Console.WriteLine(thisFruit.Color)
}
Crash !! Компилятор не остановил вас в самом начале, и в этот момент вы смотрите на код и он говорит List<Apple>
, и вы написали коди все скомпилировано.Во время выполнения о, дерьмо , свойство Color
отсутствует, потому что это Orange
.
. Поэтому оно не разрешено.