定义了这个界面:
public interface IInputBoxService<out T> {
bool ShowDialog();
T Result { get; }
}
为什么以下代码有效:
public class StringInputBoxService : IInputBoxService<string> {
...
}
...
IInputBoxService<object> service = new StringInputBoxService();
这不是吗?:
public class IntegerInputBoxService : IInputBoxService<int> {
...
}
...
IInputBoxService<object> service = new IntegerInputBoxService();
与int是值类型有什么关系吗?如果是,我该如何规避这种情况呢?
由于
答案 0 :(得分:14)
是的,它绝对与int
作为值类型有关。 C#4中的通用方差仅适用于引用类型。这主要是因为引用总是具有相同的表示:引用只是一个引用,因此CLR可以使用相同的位来表示它对象引用所知的字符串引用。 CLR可以确保代码是安全的,并使用仅在IInputBoxService<object>
传递时知道IInputBoxService<string>
的本机代码 - 从Result
返回的值将具有代表性兼容性(如果是这样的话)一个术语存在!)。
int
=&gt; object
必须有拳击等,所以你不会得到相同的代码 - 这基本上会混淆方差。
编辑:C#4.0规范在第13.1.3.2节中说明了这一点:
方差注释的目的是 提供更宽松(但仍然 类型安全)转换到接口 和委托类型。为此目的 隐式的定义(§6.1)和 显式转换(第6.2节)使用 的概念 方差可转换性,即 定义如下:类型T是方差可转换为类型 T如果T是一个 接口或声明的委托类型 使用变体类型参数T,以及每种变体类型 参数Xi以下之一 成立:
Xi是协变的,而且是 隐式引用或身份 转换从Ai到Bi
僖 是逆变的,是隐含的 参考或身份转换 存在从Bi到Ai
Xi是不变的 并且存在身份转换 艾到毕
这并不是非常明显,但基本上参考转换只存在于引用类型之间,只留下身份转换(即从类型到自身)。
至于解决方法:我认为你必须创建自己的包装类,基本上。这可以很简单:
public class Wrapper<T>
{
public T Value { get; private set; }
public Wrapper(T value)
{
Value = value;
}
}
虽然这很糟糕:(