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