2008-11-07 2 views
5

В чем смысл концепций «ковариация» и «контравариантность»?Ковариация против контравариантности в отношении наследования классов

Учитывая 2 классов, животных и слон (который наследует от Animal), я понимаю, что вы получите ошибки во время выполнения, если попытаться положить слона в массив животных, и это происходит потому, что Слон «больше» (более конкретный), чем «Животное». Но не могли бы вы поместить Животное в массив Слона, видя, как Слон гарантированно содержит свойства Животного?

+0

Полезное: http://blogs.msdn.com/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-one.aspx – 2010-03-23 05:58:48

+0

[ковариации против контрвариации] (http://izlooite.blogspot.com/2011/04/covariance-and-contravariance.html) – 2011-04-11 07:59:12

ответ

9

Вы его в обратном направлении. Вы можете добавить Elephant в массив Animal, потому что - это Animal, и у него гарантировано наличие всех методов, которые требуется Animal. Вы не можете добавить Animal в массив Elephant, потому что не имеют все методы, которые должен иметь слон.

В статье Википедии о covariance and contravariance имеет хорошее объяснение этого:

В системе типа языка программирования, оператор от типов к типам ковариантен, если она сохраняет порядок, ≤, типов, который заказывает типы от более конкретных до более общих; он контравариантен, если он меняет это упорядочение. Если ни одно из них не применяется, оператор инвариантен. Эти термины исходят из теории категорий.

Кроме того, вы сказали, что тип Elephant был «больше», и это не тот случай. Тип Animal «больше» в том смысле, что он включает в себя более конкретные типы, такие как «Слон», «Жираф» и «Лев».

0

Вы должны попробовать прочитать страницы 45-49 из Introducing .NET 4.0 With Visual Studio 2010, которые касаются этого точного примера. У него даже есть приятные фотографии слонов.

Главное, чтобы вынуть есть, чтобы сделать это

var things = new List<IThing<IContent>> { new ConcreteThing() } 

с:

public class ConcreteThing : IThing<ConcreteContent> 
{ 

} 

вам нужен «из» в определении интерфейса, что позволит более конкретные формы, чтобы быть установленный, но все, что считывается из IThing, должно быть гарантировано более общим типом.

public interface IThing<out T> where T : IContent 
{ 
} 
Смежные вопросы