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

Для параметров универсального типа ключевое слово in указывает, что параметр типа является контравариантным.For generic type parameters, the in keyword specifies that the type parameter is contravariant. Ключевое слово in может применяться в универсальных интерфейсах и делегатах.You can use the in keyword in generic interfaces and delegates.

Контравариантность позволяет использовать производные типы со степенью наследования меньше, чем у типа, заданного универсальным параметром.Contravariance enables you to use a less derived type than that specified by the generic parameter. Благодаря этому можно осуществлять неявное преобразование классов, реализующих вариантные интерфейсы, и неявное преобразование типов делегатов.This allows for implicit conversion of classes that implement variant interfaces and implicit conversion of delegate types. Ковариантность и контравариантность поддерживаются для ссылочных типов, но не для типов значений.Covariance and contravariance in generic type parameters are supported for reference types, but they are not supported for value types.

Тип может быть объявлен контравариантным в универсальном интерфейсе или делегате, только если он определяет тип параметров метода, но не тип значения, возвращаемого методом.A type can be declared contravariant in a generic interface or delegate only if it defines the type of a method's parameters and not of a method's return type. Параметры In, ref и out должны быть инвариантными, то есть не являться ковариантными или контравариантными.In, ref, and out parameters must be invariant, meaning they are neither covariant or contravariant.

Интерфейс с параметром контравариантного типа позволяет своим методам принимать аргументы производных типов, степень наследования у которых меньше, чем у параметра типа интерфейса.An interface that has a contravariant type parameter allows its methods to accept arguments of less derived types than those specified by the interface type parameter. Например, в интерфейсе IComparer<T> тип T является контравариантным, поэтому можно присвоить объект типа IComparer<Person> объекту типа IComparer<Employee> без применения каких-либо специальных методов преобразования, если Employee наследует Person.For example, in the IComparer<T> interface, type T is contravariant, you can assign an object of the IComparer<Person> type to an object of the IComparer<Employee> type without using any special conversion methods if Employee inherits Person.

Контравариантный делегат может быть назначен другому делегату того же типа, но с производным параметром универсального типа меньшей степени.A contravariant delegate can be assigned another delegate of the same type, but with a less derived generic type parameter.

Дополнительные сведения см. в разделе Ковариация и контравариантность.For more information, see Covariance and Contravariance.

Контравариантный универсальный интерфейсContravariant generic interface

В следующем примере показано, как объявить, расширить и реализовать контравариантный универсальный интерфейс.The following example shows how to declare, extend, and implement a contravariant generic interface. В нем также показано, как можно использовать неявное преобразование для классов, реализующих этот интерфейс.It also shows how you can use implicit conversion for classes that implement this interface.

// 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 generic delegate

В следующем примере кода показано, как объявить контравариантный универсальный делегат.The following example shows how to declare, instantiate, and invoke a contravariant generic delegate. В нем также показано, как можно выполнить неявное преобразование типа делегата.It also shows how you can implicitly convert a delegate type.

// 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# language specification

Дополнительные сведения см. в спецификации языка C#.For more information, see the C# Language Specification. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.The language specification is the definitive source for C# syntax and usage.

См. такжеSee also