Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Для параметров универсального типа используйте ключевое 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#.
См. также
- наружу
- Ковариантность и контравариантность
- модификаторы