【问题标题】:Question about C# 4.0's generics covariance关于 C# 4.0 的泛型协方差的问题
【发布时间】:2010-04-28 06:25:26
【问题描述】:

已经定义了这个接口:

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 是值类型有什么关系吗?如果是,我该如何规避这种情况?

谢谢

【问题讨论】:

  • 不,但据我了解,它会导致相同的结果。 int 只是 Int32 的别名。

标签: c# .net generics covariance


【解决方案1】:

是的,它绝对与 int 是一个值类型有关。 C# 4 中的泛型变体仅适用于引用类型。这主要是因为引用总是具有相同的表示:引用只是一个引用,因此 CLR 可以将相同的位用于它知道的字符串引用和对象引用。 CLR 可以确保代码是安全的,并使用在传递 IInputBoxService&lt;string&gt; 时只知道 IInputBoxService&lt;object&gt; 的本机代码 - 从 Result 返回的值将在表示上兼容(如果存在这样的术语!)。

使用int => 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;
    }
}

虽然很讨厌:(

【讨论】:

  • 我以为是这样,但我找不到参考。您是否知道任何提到差异仅适用于引用类型的 msdn 链接?
  • 这个怎么样? blogs.msdn.com/csharpfaq/archive/2010/02/16/… - 使用 Ctrl+F 查找“需要记住的重要规则”,然后您会找到条目。
  • 还有其他选择吗? Java 也为所有原始类型定义了引用类型,因此我可以不做某事,而是将其设为某事,这样可以解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-20
相关资源
最近更新 更多