【问题标题】:What does the 'in' mean in public delegate int Comparison<in T>公共委托 int 比较中的“in”是什么意思<in T>
【发布时间】:2012-05-17 19:46:48
【问题描述】:
【问题讨论】:
标签:
.net
generics
delegates
comparison
【解决方案1】:
in 表示泛型参数是逆变的。这意味着,在这种情况下,您可以将 Comparison<Base> 分配给 Comparison<Derived>。
您可以这样做,因为Comparison<Derived> 变量可以接受采用Base 类型参数的方法。当您调用Comparison<Derived> 时,您需要将Derived 变量传递给接受Base 参数的方法,这些变量恰好是有效参数。这意味着将Comparison<Base> 分配给Comparison<Derived> 是有意义的。
in 的反义词(自然)是out。这意味着参数是协变的,并且可以将Derived 泛型分配给Base 泛型。例如,这将用于指定委托的返回类型。
记住哪个是哪个的方便方法:
in 应该只用于只传入的类型。out 只应该用于只传出的类型。
在这里阅读更多:
in (Generic Modifier) (C# Reference)
Covariance and Contravariance (C# and Visual Basic)
【解决方案3】:
这个委托是逆变的,in 关键字意味着T 仅用作输入类型。逆变的意思是定义了这个委托类型:
public delegate int Comparison<in T>(T x, T y);
你可以这样做:
Comparison<Control> comp1 = (a, b) => (a.Width*a.Height - b.Width*b.Height);
Comparison<TextBox> comp2 = comp1;
如果没有in 关键字,它会抱怨第二行说它不能将一种类型转换为另一种类型。但是因为我们知道T 仅用于输入,所以将处理Control 的委托分配给预期提供(输入)TextBox 的委托指针应该是合法的。毕竟TextBox 会适合到Control。
另一方面,存在协方差。它还依赖于类型拟合到其他类型,但这次是为了结果(在这种情况下是委托的结果)。
协变和逆变统称为变体,不仅适用于泛型委托,还适用于泛型类和接口。 Variance 也适用于非泛型委托和数组,但以隐式方式,因此不需要特殊关键字 - 它可以正常工作。
方差不是一个简单的话题,我无法将我的解释与 Eric Lippert 的 series of blog articles 进行比较。虽然它是从 2007 年开始的,他在那里用将来时谈到了 .NET4 C#,但它仍然是一本非常好的读物。
【解决方案4】:
将“in”声明应用于类型参数意味着编译器将允许一个例程,该例程期望一个接受派生类型对象的委托,如果给定一个接受基类型对象的委托,它将很高兴。例如,从编译时的角度来看,一个期望委托处理 Zebras 的例程如果给定一个可以处理所有动物的委托,将会非常高兴。
然而,需要注意的重要一点是,由于MulticastDelegate 和Delegate.Combine 的不幸实现方式,尝试将协变委托与任何尝试Delegate.Combine 的代码一起使用可能会导致运行时崩溃-时间,因为Delegate.Combine 需要两个完全相同类型的委托。如果有一个通用方法来组合不同类型的委托,那就太好了(方法本身必须被赋予一个可以被两个委托都满足的类型),尽管这种组合的产品不能是MulticastDelegate (因为该类的实例仅保存一种委托类型的类型信息)。然而,目前还没有这样的方法。