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#.