gpt4 book ai didi

c# - 为什么类类型参数的方差必须与其方法的返回/参数类型参数的方差匹配?

转载 作者:可可西里 更新时间:2023-11-01 09:06:10 25 4
gpt4 key购买 nike

以下提出投诉:

interface IInvariant<TInv> {}
interface ICovariant<out TCov> {
IInvariant<TCov> M(); // The covariant type parameter `TCov'
// must be invariantly valid on
// `ICovariant<TCov>.M()'
}
interface IContravariant<in TCon> {
void M(IInvariant<TCon> v); // The contravariant type parameter
// `TCon' must be invariantly valid
// on `IContravariant<TCon>.M()'
}

但我无法想象这在哪些地方不是类型安全的。 (snip*) 这是不允许这样做的原因,还是存在其他一些我不知道的违反类型安全的情况?


* 诚然,我最初的想法是令人费解的,但尽管如此,回复还是非常彻底的,而且 @Theodoros Chatzigiannakis甚至以令人印象深刻的准确性剖析了我最初的假设。

除了回想起来的好耳光,我意识到我错误地认为 ICovariant::M 的类型签名仍然是 Func<IInvariant<Derived>>当它 ICovariant<Derived>分配给 ICovariant<Base> .然后,分配 MFunc<IInvariant<Base>>来自 ICovariant<Base>看起来很好,但当然是非法的。为什么不直接禁止这最后一个明显非法的类型转换呢? (我是这么想的)

我觉得这个错误的和切线的猜测有损于这个问题,因为 Eric Lippert还指出,但出于历史目的,被截断的部分:

The most intuitive explanation to me is that, taking ICovariant as an example, the covariant TCov implies that the method IInvariant<TCov> M() could be cast to some IInvariant<TSuper> M() where TSuper super TCov, which violates the invariance of TInv in IInvariant. However, this implication doesn't seem necessary: the invariance of IInvariant on TInv could easily be enforced by disallowing the cast of M.

最佳答案

让我们看一个更具体的例子。我们将对这些接口(interface)进行一些实现:

class InvariantImpl<T> : IInvariant<T>
{
}

class CovariantImpl<T> : ICovariant<T>
{
public IInvariant<T> M()
{
return new InvariantImpl<T>();
}
}

现在,让我们假设编译器没有提示这个并尝试以一种简单的方式使用它:

static IInvariant<object> Foo( ICovariant<object> o )
{
return o.M();
}

到目前为止一切顺利。 oICovariant<object>并且该接口(interface)保证我们有一个可以返回 IInvariant<object> 的方法.我们不必在这里执行任何转换或转换,一切都很好。现在让我们调用方法:

var x = Foo( new CovariantImpl<string>() );

因为 ICovariant是协变的,这是一个有效的方法调用,我们可以用 ICovariant<string> 代替无论哪里需要 ICovariant<object>因为这种协方差。

但是我们有一个问题。里面Foo ,我们称之为ICovariant<object>.M()并期望它返回 IInvariant<object>因为这就是ICovariant界面说它会做。但它不能那样做,因为我们传递的实际实现实际上实现了 ICovariant<string>及其 M方法返回 IInvariant<string> ,与 IInvariant<object> 没有任何关系由于该接口(interface)的不变性。它们是完全不同的类型。

关于c# - 为什么类类型参数的方差必须与其方法的返回/参数类型参数的方差匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37278996/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com