Поделиться через


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

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

Справочные документы по языку C# описывают последнюю выпущенную версию языка C#. Она также содержит начальную документацию по функциям в общедоступных предварительных версиях для предстоящего языкового выпуска.

Документация определяет любую функцию, впервые представленную в последних трех версиях языка или в текущих общедоступных предварительных версиях.

Подсказка

Чтобы узнать, когда функция впервые появилась в C#, ознакомьтесь со статьей об истории версий языка C#.

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

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

Интерфейс с параметром контрвариантного типа позволяет своим методам принимать аргументы менее производных типов, чем указанные параметром типа интерфейса. Например, в интерфейсе IComparer<T> тип T является контравариантным. Объект типа можно назначить объекту IComparer<Person>IComparer<Employee> типа без использования специальных методов преобразования, если Employee наследуется Person.

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

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

Универсальный интерфейс contravariant

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

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

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

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

См. также