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

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

使用逆变,可以使用的派生类型比泛型参数指定的类型少。 这允许隐式转换实现逆变量接口的类和委托类型的隐式转换。 引用类型支持泛型类型参数中的协变和逆变,但值类型不支持协变。

仅当类型定义方法的参数的类型而不是方法的返回类型时,才能在泛型接口中声明逆变量或委托。 In outref参数必须固定,这意味着它们既不是协变,也不是逆变。

具有逆变类型参数的接口允许其方法接受派生类型的自变量比接口类型参数指定的参数少。 例如,在接口中IComparer<T>,类型 T 是逆变的,可以在继承Person时使用任何特殊转换方法Employee将类型的对象IComparer<Person>分配给该类型的对象IComparer<Employee>

可以向逆变委托分配同一类型的另一个委托,但具有派生较少的泛型类型参数。

有关详细信息,请参阅 协变和逆变

逆变泛型接口

以下示例演示如何声明、扩展和实现逆变泛型接口。 它还演示如何对实现此接口的类使用隐式转换。

// 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# 语法和用法的明确来源。

另请参阅