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

时间:2010-04-28 06:25:27

标签: c# .net generics covariance

定义了这个界面:

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

由于

1 个答案:

答案 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;
    }
}

虽然这很糟糕:(