关于C#4.0的泛型协方差的问题

dev*_*ium 13 .net c# generics covariance

定义了这个接口:

public interface IInputBoxService<out T> {
    bool ShowDialog();
    T Result { get; }
}
Run Code Online (Sandbox Code Playgroud)

为什么以下代码有效:

public class StringInputBoxService : IInputBoxService<string> {
    ...
}

...

IInputBoxService<object> service = new StringInputBoxService();
Run Code Online (Sandbox Code Playgroud)

这不是吗?:

public class IntegerInputBoxService : IInputBoxService<int> {
    ...
}

...

IInputBoxService<object> service = new IntegerInputBoxService();
Run Code Online (Sandbox Code Playgroud)

与int是值类型有什么关系吗?如果是,我该如何规避这种情况?

谢谢

Jon*_*eet 14

是的,它绝对与int成为一种价值类型有关.C#4中的通用方差仅适用于引用类型.这主要是因为引用总是具有相同的表示:引用只是一个引用,因此CLR可以使用相同的位来表示它对象引用所知的字符串引用.CLR可以确保代码是安全的,并使用仅知道IInputBoxService<object>何时传递的本机代码IInputBoxService<string>- 返回的值Result将具有代表性兼容性(如果存在这样的术语!).

使用int=> object必须有拳击等,所以你不会得到相同的代码 - 这基本上会混淆方差.

编辑:C#4.0规范在第13.1.3.2节中说明了这一点:

方差注释的目的是为接口和委托类型提供更宽松(但仍然类型安全)的转换.为此,隐式(§6.1)和显式转换(§6.2)的定义使用了方差 - 可转换性的概念,其定义如下:如果T是一个类型,则类型T是方差可转换为类型T接口或使用变量类型参数T声明的委托类型,并且对于每个变体类型参数Xi,以下之一成立:

  • Xi是协变的,并且从Ai到Bi存在隐式参考或身份转换

  • Xi是逆变的,并且从Bi到Ai存在隐式参考或身份转换

  • Xi是不变的,并且从Ai到Bi存在身份转换

这并不是非常明显,但基本上引用转换只存在于引用类型之间,它只留下身份转换(即从类型到自身).

至于变通方法:我认为你必须创建自己的包装类,基本上.这可以很简单:

public class Wrapper<T>
{
    public T Value { get; private set; }
    public Wrapper(T value)
    {
        Value = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然很讨厌:(