分配/转换更多特定类型的IEnumerable <object>不使用structs </object>

时间:2014-07-22 13:06:22

标签: c# .net ienumerable

为什么我不能这样做:

public Form1() {
    IEnumerable<int> longEnum = new List<int>();
    IEnumerable<object> objEnum = longEnum; // <-- Compiler error
}

......但我可以这样做吗?

public Form1() {
    IEnumerable<Form1> formEnum = new List<Form1>();
    IEnumerable<object> objEnum = formEnum;
}

我的猜测是,它与int是结构的事实有关,而Form1是一个类。

我有一个函数将返回IEnumerable<object>,它的实际类型可能是更具体的,我在编译时不知道。即。

public interface IEnumFetcher{
    IEnumerable<object> GetEnumeration{ get; }
}

public class EnumGetter1 : IEnumFetcher {
    public IEnumerable<object> GetEnumeration() {
        get { return new List<long>() ;} // <-- Doesn't compile
    }
}

public class EnumGetter2 : IEnumFetcher {
    public IEnumerable<object> GetEnumeration() {
        get { return new List<string>() ;} // <-- Compiles just fine!
    }
}

public class Form1{
    public Form1(){
        var getter1 = new EnumGetter1();
        var getter2 = new EnumGetter2();

        var getting1Result = getter1.GetEnumeration();
        var getting2Result = getter2.GetEnumeration();
    }
}

现在......更重要的问题是,我如何才能实现我想要做的事情?

1 个答案:

答案 0 :(得分:1)

在C#中,方差仅适用于引用类型。来自Covariance and Contravariance FAQ

  

仅当类型参数是引用类型时才支持差异。值类型不支持差异。

从C#Spec,13.1.3.2方差转换:

  

如果T是接口或委托,则类型T<A1, …, An>可以变量转换为类型T<B1, …, Bn>   使用变量类型参数T<X1, …, Xn>声明的类型,并为每个变体类型参数Xi中的一个声明   以下是:

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

请注意,任何值类型与object之间没有隐式引用或标识转换。只有拳击转换。

原因

问题是,如果编译器可以证明T<A>可以与T<B>完全相同的方式访问T<A>T<B>只能转换为A,而不必改变IL以使其有效。

如果B或{{1}}是值类型,则两个泛型类型不可转换,因为编译器可能必须引入装箱/取消装箱指令。