使用接口的泛型进行 C# 转换
我有一些通用接口和类来实现这些接口,如下所示:
interface A<M, N>
where M : X<N>
where N : Y
{
}
class B<M, N> : A<M, N>
where M : X<N>
where N : Y
{
}
interface X<M> where M : Y
{
}
interface Y
{
}
class X1<M> : X<M> where M : Y
{
}
class Y1 : Y
{
}
我知道这似乎是一种非常混乱的做事方式,但我的应用程序需要它。我的问题是为什么我不能这样做:
A
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
马克是对的;只是为了给您更多关于为什么这不起作用的背景知识。考虑以下代码重命名:
现在您的问题是,为什么这不合法:
?
因为假设现在 IZoo 上有一个方法:
然后你说:
然后你把一个长颈鹿围场放进一个水族馆!在您想要的转换是合法的并且 IZoo 可以拥有您选择的任何方法的世界中,我们无法维护类型安全。
现在,这只是危险的,因为 IZoo 有这样的方法。如果它没有这样的方法那么你是对的,那可能是完全安全的。在 C# 4.0 中,我们向该语言添加了一项功能,以便您可以通过用“out”注释您想要协变的类型参数以及您想要的类型参数来询问编译器“检查此接口是否可以安全地变体”。与“in”相反。如果您这样做,那么编译器将检查您想要的差异是否可以成为类型安全的。如果不能,则不允许声明该类型。
StackOverflow 上出现这个问题的方式通常是人们问为什么这是非法的:
同样的原因。因为之后就没有什么可以阻止你了
,你刚刚将一只老虎添加到了长颈鹿列表中。同样的道理,只是一个更简单的情况。
Marc is right; just to give you some more background on why this cannot work. Consider the following re-naming of your code:
And now your question is, why is this not legal:
?
Because suppose now there is a method on IZoo:
And you then say:
And you just put a giraffe paddock into an aquarium! We cannot maintain type safety in a world where the conversion you want is legal and IZoo can have any method you choose on it.
Now, this is only dangerous because IZoo has such a method. If it doesn't have such a method then you are right, that could be perfectly safe. In C# 4.0 we added a feature to the language so that you can ask the compiler "check whether this interface can be made safely variant", by annotating the type parameters you want to be covariant with "out", and the ones you want to be contravariant with "in". If you do that then the compiler will check for you whether the variance you want can be made to be typesafe. If it cannot, then it will not allow the declaration of the type.
The way this question usually comes up on StackOverflow is people asking why is this illegal:
Same reason. Because then nothing stops you from later
and you've just added a tiger to a list of giraffes. Same reasoning, just a much simpler case.
方差需要明确(并且需要 C# 4.0);例如,这使其编译为协变(请注意接口中的
out
修饰符):但是请注意,这也将您的接口限制为...协变!例如,您不能使用
Add(M)
方法,因为它需要是逆变的(又名in
)。Variance needs to be explicit (and requires C# 4.0); for example, this makes it compile as covariant (note the
out
modifiers in the interface):Note, however, that this also limits your interface to ... covariance! You couldn't have an
Add(M)
method, for example - as that would need to be contavariant (akain
).