in(泛型修饰符)(C# 参考)

对于泛型类型参数,in 关键字指定该类型参数是逆变的。可以在泛型接口和委托中使用 in 关键字。

通过逆变,可以使用与泛型参数指定的派生类型相比,派生程度更小的类型。这样可以对委托类型和实现变体接口的类进行隐式转换。引用类型支持泛型类型参数中的协变和逆变,但值类型不支持。

在泛型接口或委托中,如果类型形参仅用作方法返回类型,而不用于方法实参,则可声明为协变的。 Refout 参数不能为变体。

如果接口具有逆变类型形参,则允许其方法接受与接口类型形参指定的派生类型相比,派生程度更小的类型的实参。例如,由于在 .NET Framework 4 的 IComparer<T> 接口中,类型 T 是逆变的,因此如果 Employee 继承 Person,则无需使用任何特殊转换方法,就可以将 IComparer(Of Person) 类型的对象指派给 IComparer(Of Employee) 类型的对象。

可以向逆变委托分配同一类型的其他委托,但需使用派生程度较小的泛型类型参数。

有关更多信息,请参见协变和逆变(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# 和 Visual Basic)

修饰符(C# 参考)