Intereting Posts
Разница между передачей аргумента типа ссылки C ++ и ссылкой C #? Расширяемость Visual Studio, как вы перечисляете проекты в решении? WCF NamedPipe CommunicationException – «Труба закончилась. (109, 0x6d) “. Что происходит, когда вы пытаетесь отменить запланированное сообщение шины обслуживания Azure, которое уже было установлено? Преобразование значения Eval из int в строку c # string interning Недопустимый ViewState, недопустимая длина для массива или строки char-64 Base WebRequest не имеет метода GetResponse – Windows Phone 8 должен ли баланс пользователя быть сохранен в базе данных или рассчитан динамически? TaskCompletionSource throws «Была сделана попытка перевести задачу в конечное состояние, когда она уже завершилась» как сделать исполняемую версию приложения WPF Kinect? Apple на стороне сервера уведомлений в C # Показывает индикатор выполнения, пока данные не будут получены с сервера C # Как мутировать коробку с использованием IL Когда и зачем мне реализовывать IComponent, IContainer и ISite?

c # ковариантный общий параметр

Я пытаюсь понять это, но результаты поиска не получили.

В c # 4 я могу сделать

public interface IFoo { } 

Как это отличается от

  public interface IFoo { } 

Все, что я знаю, это то out что общий параметр ковариант (??). Может ли кто-нибудь объяснить использование части с примером? А также почему применимо только для интерфейсов и делегатов, а не для classов?

Извините, если это дубликат и закрыть его как таковой, если он есть.

Может ли кто-нибудь объяснить использование части Т с примером?

Конечно. IEnumerable является ковариантным. Это означает, что вы можете сделать это:

 static void FeedAll(IEnumerable animals) { foreach(Animal animal in animals) animal.Feed(); } ... IEnumerable giraffes = GetABunchOfGiraffes(); FeedAll(giraffes); 

«Ковариант» означает, что отношение совместимости присваивания аргумента типа сохраняется в родовом типе . Giraffe – это присвоение, совместимое с Animal , и поэтому эта связь сохраняется в построенных типах: IEnumerable – это присвоение, совместимое с IEnumerable .

Почему применимо только для интерфейсов и делегатов, а не для classов?

Проблема с classами состоит в том, что classы имеют тенденцию иметь изменяемые поля. Давайте возьмем пример. Предположим, мы допустили следующее:

 class C { private T t; 

Хорошо, теперь подумайте над этим вопросом, прежде чем продолжить. Может ли C использовать какой-либо метод вне конструктора, который устанавливает поле t в значение, отличное от его значения по умолчанию?

Поскольку он должен быть typeafe, C теперь не может иметь методов, которые принимают T как аргумент; T может быть возвращен только. Итак, кто устанавливает t, и где они получают значение, из которого они его выбрали ?

Ковариантные типы classов действительно работают только в том случае, если class неизменен . И у нас нет хорошего способа сделать неизменные classы на C #.

Хотелось бы, чтобы мы это сделали, но нам нужно жить с системой типа CLR, которую нам дали. Я надеюсь, что в будущем мы сможем лучше поддерживать как неизменные classы, так и ковариантные classы.

Если эта функция вас интересует, подумайте о том, чтобы прочитать мою длинную серию о том, как мы разработали и внедрили эту функцию. Начните снизу:

https://blogs.msdn.microsoft.com/ericlippert/tag/covariance-and-contravariance/

Если мы говорим об общей дисперсии:

Ковариация – это все значения, возвращаемые из операции обратно вызывающему.

Контравариантность Это противоположность, и речь идет о значениях, передаваемых вызывающим:

Из того, что я знаю, если параметр типа используется только для вывода, вы можете использовать его. Однако, если тип используется только для ввода, вы можете использовать его. Это удобство, потому что компилятор не может быть уверен, что вы можете вспомнить, какая форма называется ковариацией и которая называется контравариантностью. Если вы не объявляете их явно после объявления типа, соответствующие типы преобразования доступны неявно .

В classах нет дисперсии (ковариации или контравариантности), потому что даже если у вас есть class, который использует только параметр типа для ввода (или использует его только для вывода), вы не можете указать модификаторы in или out. Только интерфейсы и delegates могут иметь параметры типа варианта. Во-первых, CLR этого не допускает. С концептуальной точки зрения интерфейсы представляют собой способ взглянуть на объект с определенной точки зрения, тогда как classы являются более актуальными типами реализации .

Это означает, что если у вас есть это:

 class Parent { } class Child : Parent { } 

Затем экземпляр IFoo также является экземпляром IFoo .