Применительно к обобщенному интерфейсу контравариантность служит сред- . ством, разрешающим методу использовать аргумент, тип которого относится к базовому классу, указанному в соответствующем параметре типа. В прошлом тип аргумента метода должен был в точности соответствовать параметру типа в силу строгой проверки обобщений на соответствие типов. Контравариантность смягчает это строгое правило таким образом, чтобы обеспечить типовую безопасность. Параметр контрава-риантного типа объявляется с помощью ключевого словаin,которое предваряет имя этого параметра.
Для того чтобы стали понятнее последствия применения ковариантности, вновь обратимся к конкретному примеру. Ниже приведен обобщенный интерфейсIMyContraVarGenlFконтравариантного типа. В нем указывается контравариантный параметр обобщенного типаТ,который используется в объявлении методаShow .
// Это обобщенный интерфейс, поддерживающий контравариантность. public interface IMyContraVarGenIF
}
Как видите, обобщенный типТуказывается в данном интерфейсе как контравариантный с помощью ключевого словаin,предшествующего имени его параметра. Обратите также внимание на то, чтоТявляется параметром типа для аргументаobjв методеShow .
• Далее интерфейсIMyContraVarGenlFреализуется в классеMyClass,как показано ниже.
// Реализовать интерфейс IMyContraVarGenlF. class MyClass
public void Show(T x) { Console.WriteLine(x); }
}
В данном случае методShow просто выводит на экран строковое представление переменнойх,получаемое в результате неявного обращения к методуToString из методаWriteLine .
После этого объявляется иерархия классов, как показано ниже.
// Создать простую иерархию классов, class Alpha {
public override string ToString { return "Это объект класса Alpha.";
}
// ...
}
class Beta : Alpha {
public override string ToString {
return "Это объект класса Beta.";
}
// ...
}
Ради большей наглядности классыAlphaиBetaнесколько отличаются от аналогичных классов из предыдущего примера применения ковариантности. Обратите также внимание на то, что методToString переопределяется таким образом, чтобы возвращать тип объекта.
С учетом всего изложенного выше, следующая последовательность операций будет считаться вполне допустимой.
// Создать ссылку из интерфейса IMyContraVarGenIF
//на объект типа MyClass
// Это вполне допустимо как при наличии контравариантности, так и без нее. IMyContraVarGenIF
// Создать ссылку из интерфейса IMyContraVarGenIF
// на объект типа MyClass