Ради большей наглядности примера вся рассмотренная выше последовательность операций собрана ниже в единую программу.

// Продемонстрировать ковариантность в обобщенном интерфейсе, using System;

// Этот обобщенный интерфейс поддерживает ковариантность. public interface IMyCoVarGenIF<out Т> {

Т GetObjectO;

}

// Реализовать интерфейс IMyCoVarGenlF. class MyClass<T> : IMyCoVarGenIF<T> {

T obj;

public MyClass(T v) { obj = v; } public T GetObjectO { return obj; }

}

// Создать простую иерархию классов, class Alpha { string name;

public string GetNameO { return name; }

// ...

}

class Beta : Alpha {

public Beta(string n) : base(n) { }

// ...

}

class VarianceDemo { static void Main() {

// Создать ссылку из интерфейса IMyCoVarGenlF на объект типа MyClass<Alpha>.

// Это вполне допустимо как при наличии ковариантности, так и без нее. IMyCoVarGenIF<Alpha> AlphaRef = new MyClass<Alpha>(new Alpha('Alpha #1'));

Console.WriteLine('Имя объекта, на который ссылается переменная ' +

'AlphaRef: ' + AlphaRef.GetObj ect().GetName());

//А теперь создать объект MyClass<Beta> и присвоить его // переменной AlphaRef.

// *** Эта строка кода вполне допустима благодаря ковариантности. *** AlphaRef = new MyClass<Beta>(new Beta('Beta #1'));

Console.WriteLine('Имя объекта, на который теперь ссылается переменная ' + 'AlphaRef: ' + AlphaRef.GetObj ect() .GetName());

}

}

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

Имя объекта, на который ссылается переменная AlphaRef: Alpha #1 Имя объекта, на который теперь ссылается переменная AlphaRef: Beta #1

Следует особо подчеркнуть, что переменной AlphaRef можно присвоить ссылку на объект типа MyClass<Beta> благодаря только тому, что обобщенный тип Т указан как ковариантный в интерфейсе IMyCoVarGenlF. Для того чтобы убедиться в этом, удалите ключевое слово out из объявления параметра обобщенного типа Т в интерфейсе IMyCoVarGenlF и попытайтесь скомпилировать данную программу еще раз. Компиляция завершится неудачно, поскольку строгая проверка на соответствие типов не разрешит теперь подобное присваивание.

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

public interface IMyCoVarGenIF2<out Т> : IMyCoVarGenIF<T> {

// ...

}

Обратите внимание на то, что ключевое слово out указано только в объявлении расширенного интерфейса. Указывать его в объявлении базового интерфейса не только не нужно, но и не допустимо. И последнее замечание: обобщенный тип Т допускается не указывать как ковариантный в объявлении интерфейса IMyCoVarGenIF2. Но при этом исключается ковариантность, которую может обеспечить расширенный интерфейс

IMyCoVarGetlF. Разумеется, возможность сделать интерфейс IMyCoVarGenIF2 инвариантным может потребоваться в некоторых случаях его применения.

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату