Добавить в цитаты Настройки чтения

Страница 300 из 502

<b>  public override string ToString() {</b>

<b>    return &quot;Это объект класса Alpha.&quot;;</b>

<b>  }</b>

<b>  // ...</b>

<b>}</b>

<b>class Beta : Alpha {</b>

<b>  public override string ToString() {</b>

<b>    return &quot;Это объект класса Beta.&quot;;</b>

<b>  }</b>

<b>  // ...</b>

<b>}</b>

Ради большей наглядности классы Alpha и Beta несколько отличаются от аналогичных классов из предыдущего примера применения ковариантности. Обратите также внимание на то, что метод ToString() переопределяется таким образом, чтобы возвращать тип объекта.

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

<b>// Создать ссылку из интерфейса IMyContraVarGenIF&lt;Alpha&gt;</b>

<b>//на объект типа MyClass&lt;Alpha&gt;.</b>

<b>// Это вполне допустимо как при наличии контравариантности, так и без нее.</b>

<b> IMyContraVarGenIF&lt;Alpha&gt; AlphaRef = new MyClass&lt;Alpha&gt;();</b>

<b>// Создать ссылку из интерфейса IMyContraVarGenIF&lt;beta&gt;</b>

<b>// на объект типа MyClass&lt;Beta&gt;.</b>

<b>//И это вполне допустимо как при наличии контравариантности, так и без нее.</b>

<b>IMyContraVarGenIF&lt;Beta&gt; BetaRef = new MyClass&lt;Beta&gt;();</b>

<b>// Создать ссылку из интерфейса IMyContraVarGenIF&lt;beta&gt;</b>

<b>// на объект типа MyClass&lt;Alpha&gt;.</b>

<b>// *** Это вполне допустимо благодаря контравариантности. ***</b>

<b>IMyContraVarGenIF&lt;Beta&gt; BetaRef2 = new MyClass&lt;Alpha&gt;();</b>

<b>// Этот вызов допустим как при наличии контравариантности, так и без нее.</b>

<b>BetaRef.Show(new Beta());</b>

<b>// Присвоить переменную AlphaRef переменной BetaRef.</b>

<b>// *** Это вполне допустимо благодаря контравариантности. ***</b>

<b>BetaRef = AlphaRef;</b>

<b>BetaRef.Show(new Beta());</b>

Прежде всего, обратите внимание на создание двух переменных ссылочного типа IMyContraVarGenIF, которым присваиваются ссылки на объекты класса MyClass, где параметры типа совпадают с аналогичными параметрами в интерфейсных ссылках. В первом случае используется параметр типа Alpha, а во втором — параметр типа Beta. Эти объявления не требуют контравариантности и допустимы в любом случае.

Далее создается переменная ссылочного типа IMyContraVarGenIF&lt;Beta&gt;, но на этот раз ей присваивается ссылка на объект класса MyClass&lt;Alpha&gt;. Эта операция вполне допустима, поскольку обобщенный тип Т объявлен как контравариантный.

Как и следовало ожидать, следующая строка, в которой вызывается метод BetaRef.Show() с аргументом Beta, является вполне допустимой. Ведь Beta — это обобщенный тип Т в классе MyClass&lt;Beta&gt; и в то же время аргумент в методе Show().

В следующей строке переменная AlphaRef присваивается переменной BetaRef. Эта операция вполне допустима лишь в силу контравариантности. В данном случае переменная относится к типу MyClass<Beta>, а переменная AlphaRef — к типу MyClass&lt;Alpha&gt;. Но поскольку Alpha является базовым классом для класса Beta, то такое преобразование типов оказывается допустимым благодаря контравариантности. Для того чтобы убедиться в необходимости контравариантности в рассматриваемом здесь примере, попробуйте удалить ключевое слово in из объявления обобщенного типа Т в интерфейсе IMyContraVarGenIF, а затем попытайтесь скомпилировать приведенный выше код еще раз. В результате появятся ошибки компиляции.

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

<b>// Продемонстрировать контравариантность в обобщенном интерфейсе,</b>

<b>using System;</b>

<b>// Это обобщенный интерфейс, поддерживающий контравариантность.</b>

<b>public interface IMyContraVarGenIF&lt;in T&gt; {</b>

<b>  void Show(T obj);</b>

<b>}</b>

<b>// Реализовать интерфейс IMyContraVarGenIF.</b>

<b>class MyClass&lt;T&gt; : IMyContraVarGenIF&lt;T&gt; {</b>

<b>  public void Show(T x) {</b>

<b>    Console.WriteLine(x);</b>

<b>  }</b>

<b>}</b>

<b>// Создать простую иерархию классов,</b>

<b>class Alpha {</b>

<b>  public override string ToString() {</b>