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

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

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

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

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

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

Дополнительные сведения см. в разделе Ковариация и контравариация (C# и Visual Basic).

Пример

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

// Contravariant interface. 
interface IContravariant<in A> { }

// Extending contravariant interface. 
interface IExtContravariant<in A> : IContravariant<A> { }

// Implementing contravariant interface. 
class Sample<A> : IContravariant<A> { }

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

        // You can assign iobj to istr because 
        // the IContravariant interface is contravariant.
        istr = iobj;
    }
}

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

// Contravariant delegate. 
public delegate void DContravariant<in A>(A argument);

// Methods that match the delegate signature. 
public static void SampleControl(Control control)
{ }
public static void SampleButton(Button button)
{ }

public void Test()
{

    // Instantiating the delegates with the methods.
    DContravariant<Control> dControl = SampleControl;
    DContravariant<Button> dButton = SampleButton;

    // You can assign dControl to dButton 
    // because the DContravariant delegate is contravariant.
    dButton = dControl;

    // Invoke the delegate.
    dButton(new Button()); 
}

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

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

См. также

Ссылки

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

Модификаторы (Справочник по C#)

Другие ресурсы

Ковариация и контравариация (C# и Visual Basic)