Out (универсальный модификатор) (Visual Basic)

Для параметров Out универсального типа ключевое слово указывает, что тип является ковариантным.

Замечания

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

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

Правила

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

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

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

    Примечание.

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

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

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

Ковариация и контравариантность поддерживаются для ссылочных типов, но не для типов значений.

В Visual Basic нельзя объявлять события в ковариантных интерфейсах без указания типа делегата. Кроме того, ковариантные интерфейсы не могут содержать вложенные классы, перечисления или структуры, но они могут иметь вложенные интерфейсы.

Поведение

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

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

Пример 1

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

' Covariant interface.
Interface ICovariant(Of Out R)
End Interface

' Extending covariant interface.
Interface IExtCovariant(Of Out R)
    Inherits ICovariant(Of R)
End Interface

' Implementing covariant interface.
Class Sample(Of R)
    Implements ICovariant(Of R)
End Class

Sub Main()
    Dim iobj As ICovariant(Of Object) = New Sample(Of Object)()
    Dim istr As ICovariant(Of String) = New Sample(Of String)()

    ' You can assign istr to iobj because
    ' the ICovariant interface is covariant.
    iobj = istr
End Sub

Пример 2

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

' Covariant delegate.
Public Delegate Function DCovariant(Of Out R)() As R

' Methods that match the delegate signature.
Public Shared Function SampleControl() As Control
    Return New Control()
End Function

Public Shared Function SampleButton() As Button
    Return New Button()
End Function

Private Sub Test()

    ' Instantiating the delegates with the methods.
    Dim dControl As DCovariant(Of Control) =
        AddressOf SampleControl
    Dim dButton As DCovariant(Of Button) =
        AddressOf SampleButton

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

    ' Invoke the delegate.
    dControl()
End Sub

См. также