双重协方差

时间:2011-07-22 23:18:41

标签: c# covariance

我有

public interface IFoo
{
   IEnumerable<IThingy> Thingies{get;}
}

我希望能够做到

class Thing1 : IThingy
{
   ...
}
class ImplementFoo : IFoo
{
   List<Thing1> m_things;
   IEnumerable<IThingy> Thingies {get {return m_things;}}
}

ImplementFoo.Thingies返回Thing1s的IList(它是IEnumerable)(它是IThings)。所以理论上这个代码应该可行,但事实并非如此。 VS建议在吸气器中投射;编译但在运行时失败。我在c#4中期待过多的协方差吗?

VS 2010 - &gt; Silverlight 4.这是编译错误

  

无法将类型“System.Collections.Generic.List<MyProj.Column>”隐式转换为“System.Collections.Generic.IEnumerable<MyProj.IColumn>”。存在显式转换(您是否错过了演员?)

编辑:人们告诉我这应该有用,但它在SL4中不起作用

3 个答案:

答案 0 :(得分:2)

这在C#/ .NET 4中运行良好。这是一个完整的,编译和工作的示例:

namespace Test
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public interface IThingy { }

    public interface IFoo
    {
        IEnumerable<IThingy> Thingies { get; }
    }

    internal class Thing1 : IThingy { }

    internal class ImplementFoo : IFoo
    {
        private List<Thing1> m_things = new List<Thing1>() { new Thing1() };

        public IEnumerable<IThingy> Thingies
        {
            get { return m_things; }
        }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            var impl = new ImplementFoo();

            Console.WriteLine(impl.Thingies.Count());


            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }
}

我怀疑问题是你的目标是.NET 3.5sp1或更早版本,而不是.NET 4.0。协方差只有在针对.NET 4时才能正常工作,因为它需要新的框架更改。在这种情况下,.NET 4中的IEnumerable<T>实际上是IEnumerable<out T>,这是必须的。

答案 1 :(得分:1)

您可以使用Cast extension method

class ImplementFoo : IFoo
{
    List<Thing1> m_things;

    IEnumerable<IThingy> Thingies 
    {
        get
        {
            return m_things.Cast<IThingy>();
        }
    }
}

这是因为IEnumerable<Thing1>没有隐式实现IEnumerable<IThingy>

答案 2 :(得分:0)

这是SL4和CLR4之间的区别。 IEnumerable接口未标记为“out”。显然已在SL5中修复