Мангуст - решение сложной проверки, которая зависит от других моделей

Это очень часто задаваемый вопрос. Давайте переименуем ваши типы:

abstract class Fruit { }                    // was BaseViewPresenter
abstract class FruitBowl where T : Fruit // was BaseView
class Apple : Fruit { }                     // was LoginPresenter
class BowlOfApples : FruitBowl {  }  // was LoginView

Теперь ваш вопрос:

У меня есть BowlOfApples, который наследуется от FruitBowl. Почему я не могу использовать его как FruitBowl? Яблоко - это плод, поэтому чаша с яблоками - это миска с фруктами.

blockquote>

Нет, это не так. Вы можете положить банан в миску с фруктами, но вы не можете положить банан в миску с яблоками, и поэтому чаша с яблоками - это не чаша с фруктами. (И по аналогичным соображениям, миска с фруктами также не является чашей из яблок.) Поскольку операции, которые вы можете законно выполнять на двух типах, отличаются , они не могут быть совместимыми .

Вот фотография легенды StackOverflow Jon Skeet, демонстрирующая этот факт:

enter image description here [/g6]

Вы хотите, чтобы функция общая контравариантность , и поддерживается только на интерфейсах интерфейсов и делегатов , когда компилятор может доказать, что дисперсия безопасна, а когда переменный тип является ссылкой тип. Например, вы можете использовать IEnumerable в контексте, где требуется IEnumerable, потому что компилятор может проверить, что вы не можете поместить Banana в последовательность фруктов.

Проведите поиск по «ковариации и ковариации C #» на этом сайте или в Интернете, и вы найдете гораздо больше информации о том, как работает эта функция. В частности, моя серия статей о том, как мы разработали и реализовали эту функцию на C # 4, начинается здесь: http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and- контрвариантность-в-с-часть-one.aspx

0
задан Daniel Valland 31 December 2018 в 00:25
поделиться