in (универсальный модификатор) (Справочник по C#)
Для параметров универсального типа ключевое слово in указывает, что тип параметра является контравариантным.Ключевое слово in может применяться в универсальных интерфейсах и делегатах.
Контравариантность позволяет использовать производный тип меньшей глубины наследования, нежели у типа, заданного универсальным параметром.Благодаря этому можно осуществлять неявное преобразование классов, реализующих вариантные интерфейсы, и неявное преобразование типов делегатов.Ковариантность и контравариантность в параметрах универсального типа поддерживаются для ссылочных типов, но не для типов значений.
В универсальном интерфейсе или делегате тип может быть объявлен ковариантным, если он используется только как тип аргументов метода и не используется как возвращаемый тип метода.Параметры Ref и out не могут иметь тип Variant.
Интерфейс с параметром контравариантного типа позволяет своим методам принимать аргументы производных типов, глубина наследования у которых меньше, чем у типов, заданных параметром типа интерфейса.Например, поскольку в интерфейсе IComparer<T> в .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#)