IMyContraVarGenIF BetaRef = new MyClass();

// Создать ссылку из интерфейса IMyContraVarGenIF

//на объект типа MyClass.

// *** Это вполне допустимо благодаря контравариантности. *** IMyContraVarGenIF BetaRef2 = new MyClass();

// Этот вызов допустим как при наличии контравариантности, так и без нее. BetaRef.Show(new Beta());

// Присвоить переменную AlphaRef переменной BetaRef.

// *** Это вполне допустимо благодаря контравариантности. ***

BetaRef = AlphaRef;

BetaRef.Show(new Beta ());

}

}

Выполнение этой программы дает следующий результат.

Это объект класса Beta.

Это объект класса Beta.

Контравариантный интерфейс может быть расширен аналогично описанному выше расширению ковариантного интерфейса. Для достижения контравариантного характера расширенного интерфейса в его объявлении должен быть указан такой же параметр обобщенного типа, как и у базового интерфейса, но с ключевым словом in, как показано ниже.

public interface IMyContraVarGenIF2 : IMyContraVarGenIF {

// ...

}

Следует иметь в виду, что указывать ключевое словоinв объявлении базового интерфейса не только не нужно, но и не допустимо. Более того, сам расширенный интерфейсIMyContraVarGenIF2не обязательно должен быть контравариантным. Иными словами, обобщенный типТв интерфейсеIMyContraVarGenIF2не требуется модифицировать ключевым словомin.Разумеется, все преимущества, которые сулит контравариантность в интерфейсеIMyContraVarGen,при этом будут утрачены в интерфейсеIMyContraVarGenIF2.

Контравариантность оказывается пригодной только для ссылочных типов, а параметр контравариантного типа можно применять только к аргументам методов. Следовательно, ключевое слово in нельзя указывать в параметре типа, используемом в качестве возвращаемого типа.

Вариантные делегаты

Как пояснялось в главе 15, ковариантность и контравариантность поддерживается в необобщенных делегатах в отношении типов, возвращаемых методами, и типов, указываемых при объявлении параметров. Начиная с версии C# 4.0, возможности ковариантности и контравариантности были распространены и на обобщенные делегаты. Подобные возможности действуют таким же образом, как было описано выше в отношении обобщенных интерфейсов.

Ниже приведен пример контравариантного делегата.

// Объявить делегат, контравариантный по отношению к обобщенному типу Т. delegate bool SomeOpcin Т>(Т obj);

Этому делегату можно присвоить метод с параметром обобщенного типаТили же класс, производный от типаТ.

А вот пример ковариантного делегата.

Перейти на страницу:

Похожие книги