Применение ковариантности в обобщенном интерфейсе
Применительно к обобщенному интерфейсу ковариантность служит средством, разрешающим методу возвращать тип, производный от класса, указанного в параметре типа. В прошлом возвращаемый тип должен был в точности соответствовать параметру типа в силу строгой проверки обобщений на соответствие типов. Ковариантность смягчает это строгое правило таким образом, чтобы обеспечить типовую безопасность. Параметр ковариантного типа объявляется с помощью ключевого словаout,которое предваряет имя этого параметра.
Для того чтобы стали понятнее последствия применения ковариантности, обратимся к конкретному примеру. Ниже приведен очень простой интерфейсIMyCoVarGenlF,в котором применяется ковариантность.
//В этом обобщенном интерфейсе поддерживается ковариантность, public interface IMyCoVarGenlFCout Т> {
Т GetObject;
}
Обратите особое внимание на то, как объявляется параметр обобщенного типаТ.Его имени предшествует ключевое словоout.В данном контексте ключевое словоoutобозначает, что обобщенный типТявляется ковариантным. А раз он ковариантный, то методGetOb j ect может возвращать ссылку на обобщенный типТили же ссылку на любой класс, производный от типаТ.
Несмотря на свою ковариантность по отношению к обобщенному типуТ,интерфейсIMyCoVarGenlFреализуется аналогично любому другому обобщенному интерфейсу. Ниже приведен пример реализации этого интерфейса в классеMyClass.
// Реализовать интерфейс IMyCoVarGenlF. class MyClass
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 GetNameO { return name; }
// ...
}
class Beta : Alpha {
public Beta(string n) : base (n) { }
// ...
}
Как видите, классBetaявляется производным от классаAlpha.
С учетом всего изложенного выше, следующая последовательность операций будет считаться вполне допустимой.
// Создать ссылку из интерфейса IMyCoVarGenlF на объект типа MyClass
// Это вполне допустимо как при наличии ковариантности, так и без нее. IMyCoVarGenIF
new MyClass