out (универсальный модификатор) (Справочник по C#)

Для параметров универсального типа ключевое слово out указывает, что параметр типа является ковариантным. Ключевое слово out может применяться в универсальных интерфейсах и делегатах.

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

Интерфейс с параметром ковариантного типа позволяет своим методам возвращать аргументы производных типов, степень наследования у которых больше, чем у параметра типа. Например, так как в .NET Framework 4 в IEnumerable<T> тип T является ковариантным, можно назначить объект типа IEnumerable(Of String) объекту типа IEnumerable(Of Object) без применения каких-либо специальных методов преобразования.

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

Дополнительные сведения см. в разделе Ковариация и контравариантность.

Пример — ковариантный универсальный интерфейс

В следующем примере показано, как объявить, расширить и реализовать ковариантный универсальный интерфейс. В нем также показано, как использовать неявное преобразование для классов, реализующих ковариантный интерфейс.

// Covariant interface.
interface ICovariant<out R> { }

// Extending covariant interface.
interface IExtCovariant<out R> : ICovariant<R> { }

// Implementing covariant interface.
class Sample<R> : ICovariant<R> { }

class Program
{
    static void Test()
    {
        ICovariant<Object> iobj = new Sample<Object>();
        ICovariant<String> istr = new Sample<String>();

        // You can assign istr to iobj because
        // the ICovariant interface is covariant.
        iobj = istr;
    }
}

В универсальном интерфейсе параметр типа может быть объявлен ковариантным, если он удовлетворяет следующим условиям:

  • Параметр типа используется только в качестве типа значения, возвращаемого методами интерфейса, и не используется в качестве типа аргументов метода.

    Примечание.

    Существует одно исключение из данного правила. Если в ковариантном интерфейсе в качестве параметра метода используется контравариантный универсальный делегат, ковариантный тип можно использовать в качестве параметра универсального типа для этого делегата. Дополнительные сведения о ковариантных и контравариантных универсальных методах-делегатах см. в разделе Вариативность в делегатах и Использование вариативности в универсальных методах-делегатах Func и Action.

  • Параметр типа не используется в качестве универсального ограничения для методов интерфейса.

Пример — ковариантный универсальный метод-делегат

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

// Covariant delegate.
public delegate R DCovariant<out R>();

// Methods that match the delegate signature.
public static Control SampleControl()
{ return new Control(); }

public static Button SampleButton()
{ return new Button(); }

public void Test()
{
    // Instantiate the delegates with the methods.
    DCovariant<Control> dControl = SampleControl;
    DCovariant<Button> dButton = SampleButton;

    // You can assign dButton to dControl
    // because the DCovariant delegate is covariant.
    dControl = dButton;

    // Invoke the delegate.
    dControl();
}

В универсальном методе-делегате тип может быть объявлен ковариантным, если он используется только как тип значения, возвращаемого методом, и не используется для аргументов метода.

Спецификация языка C#

Дополнительные сведения см. в спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.

См. также