Страница 298 из 502
<b> }</b>
<b>}</b>
Обратите внимание на то, что ключевое слово out не указывается еще раз в выражении, объявляющем реализацию данного интерфейса в классе MyClass. Это не только не нужно, но и вредно, поскольку всякая попытка еще раз указать ключевое слово out будет расцениваться компилятором как ошибка.
А теперь рассмотрим следующую простую реализацию иерархии классов.
<b>// Создать простую иерархию классов,</b>
<b>class Alpha {</b>
<b> string name;</b>
<b> public Alpha(string n) { name = n; }</b>
<b> public string GetName() { return name; }</b>
<b>// ...</b>
<b>}</b>
<b>class Beta : Alpha {</b>
<b> public Beta(string n) : base (n) { }</b>
<b>// ...</b>
<b>}</b>
Как видите, класс Beta является производным от класса Alpha.
С учетом всего изложенного выше, следующая последовательность операций будет считаться вполне допустимой.
<b>// Создать ссылку из интерфейса IMyCoVarGenIF на объект типа MyClass<Alpha>.</b>
<b>// Это вполне допустимо как при наличии ковариантности, так и без нее.</b>
<b>IMyCoVarGenIF<Alpha> AlphaRef =</b>
<b> new MyClass<Alpha>(new Alpha("Alpha #1"));</b>
<b>Console.WriteLine("Имя объекта, на который ссылается переменная AlphaRef: " +</b>
<b> AlphaRef.GetObject().GetName());</b>
<b>//А теперь создать объект MyClass<Beta> и присвоить его переменной AlphaRef.</b>
<b>// *** Эта строка кода вполне допустима благодаря ковариантности. ***</b>
<b>AlphaRef = new MyClass<Beta>(new Beta("Beta #1"));</b>
<b>Console.WriteLine("Имя объекта, на который теперь ссылается " +</b>
<b> "переменная AlphaRef: " + AlphaRef.GetObject().GetName());</b>
Прежде всего, переменной AlphaRef типа IMyCoVarGenIF<Alpha> в этом фрагменте кода присваивается ссылка на объект типа MyClass<Alpha>. Это вполне допустимая операция, поскольку в классе MyClass реализуется интерфейс IMyCoVarGenIF, причем и в том, и в другом в качестве аргумента типа указывается Alpha. Далее имя объекта выводится на экран при вызове метода GetName() для объекта, возвращаемого методом GetObject(). И эта операция вполне допустима, поскольку Alpha — это и тип, возвращаемый методом GetName(), и обобщенный тип Т. После этого переменной AlphaRef присваивается ссылка на экземпляр объекта типа MyClass<Beta>, что также допустимо, потому что класс Beta является производным от класса Alpha, а обобщенный тип Т — ковариантным в интерфейсе IMyCoVarGenIF. Если бы любое из этих условий не выполнялось, данная операция оказалась бы недопустимой.
Ради большей наглядности примера вся рассмотренная выше последовательность операций собрана ниже в единую программу.
<b>// Продемонстрировать ковариантность в обобщенном интерфейсе,</b>
<b>using System;</b>
<b>// Этот обобщенный интерфейс поддерживает ковариантность.</b>
<b>public interface IMyCoVarGenIF<out Т> {</b>
<b> Т GetObject();</b>
<b>}</b>
<b>// Реализовать интерфейс IMyCoVarGenIF.</b>
<b>class MyClass<T> : IMyCoVarGenIF<T> {</b>
<b> T obj;</b>
<b> public MyClass(T v) { obj = v; }</b>
<b> public T GetObject() { return obj; }</b>
<b>}</b>
<b>// Создать простую иерархию классов,</b>
<b>class Alpha {</b>
<b> string name;</b>
<b> public Alpha(string n) { name = n; }</b>
<b> public string GetName() { return name; }</b>
<b> // ...</b>
<b>}</b>
<b>class Beta : Alpha {</b>
<b> public Beta(string n) : base(n) { }</b>
<b> // ...</b>
<b>}</b>
<b>class VarianceDemo {</b>
<b> static void Main() {</b>
<b> // Создать ссылку из интерфейса IMyCoVarGenIF на объект типа MyClass<Alpha>.</b>
<b> // Это вполне допустимо как при наличии ковариантности, так и без нее. </b>
<b> IMyCoVarGenIF<Alpha> AlphaRef =</b>