c# – 为什么通用接口默认不是co / contravariant?

例如,IEnumerable< T>接口:

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

在该接口中,通用类型仅用作接口方法的返回类型,不用作方法参数的类型,因此它可以是协方差的.给出这一点,理论上不能编译从接口推断方差?如果可以的话,为什么C#需要我们明确设定co / contravariance关键字.

更新:正如Jon Skeet提到的,这个问题可以分为以下几个小问题:

编译器可以通过在当前通用类型中如何使用所有的基类型来推断通用类型的co / contravariance?

例如.. .NET Framework 4.0中有多少个通用接口参数可以自动标记为co / contravariant,没有任何歧义?约70%,80%,90%或100%?
>如果可以的话,默认情况下是否适用于通用类型的co / contravariance?至少能够从类型使用中分析和推断出共同/违规的那些类型.

那么这里有两个问题.首先,编译器是否可以这么做?其次,(如果可以的话)?

对于第一个问题,我会推迟到Eric Lippert,当我在深度C#的第二版中提到这个问题时,他发表了这个评论:

It’s not clear to me that we reasonably could even if we wanted to. We can easily come up
with situations that require expensive global analysis of all the interfaces in a program
to work out the variances, and we can easily come up with situations where either it’s
<in T, out U> or <out T, in U> and no way to decide between them. With both bad
performance and ambiguous cases it’s an unlikely feature.

(我希望埃里克不介意我这个逐字的引用;他以前一直很好分享这样的见解,所以我要去过去的形式:)

另一方面,我怀疑仍然可以推测出没有歧义的情况,所以第二点依然是相关的

即使编译器能明确地知道它只是以一种方式有效,我不认为它应该是自动的.扩展接口在某种程度上永远是一个突破性的变化,一般来说,如果您是唯一实现的接口.但是,如果人们依赖于您的界面来变形,那么您可能无法在不破坏客户端的情况下添加方法,即使他们只是调用者而不是实现者.您添加的方法可能会将以前的协方差接口更改为不变的,此时您将破坏任何尝试共同使用的呼叫者.

基本上,我认为要明确这是很好的 – 这是一个设计决定,你应该有意识地进行,而不是只是意外地结束了协方差/逆向,而没有考虑过.

http://stackoverflow.com/questions/3603426/why-generic-interfaces-are-not-co-contravariant-by-default

转载注明原文:c# – 为什么通用接口默认不是co / contravariant?