C# 双重协方差

C# 双重协方差,c#,covariance,C#,Covariance,我有 公共接口IFoo { IEnumerable Thingies{get;} } 我想这样做 public interface IFoo { IEnumerable<IThingy> Thingies{get;} } class Thing1:i Thingy { ... } 类实现foo:IFoo { 列出你的事情; IEnumerable Thingies{get{return m_things;}} } Thingies返回thing1的IList(它是IEnu

我有

公共接口IFoo
{
IEnumerable Thingies{get;}
}
我想这样做

public interface IFoo
{
   IEnumerable<IThingy> Thingies{get;}
}
class Thing1:i Thingy
{
...
}
类实现foo:IFoo
{
列出你的事情;
IEnumerable Thingies{get{return m_things;}}
}
Thingies返回thing1的IList(它是IEnumerable)(它是i字符串)。因此,理论上,这段代码应该有效,但事实并非如此。VS建议在getter中加入一个角色;可编译但在运行时失败的。我是否对c#4的协方差期望过高

VS2010->Silverlight 4。下面是编译错误

无法将类型“
System.Collections.Generic.List
”隐式转换为“
System.Collections.Generic.IEnumerable
”。存在显式转换(是否缺少强制转换?)

编辑:人们告诉我这应该行得通,但在SL4中行不通。你可以使用:

类实现foo:IFoo
{
列出你的事情;
数不清的东西
{
得到
{
返回m_things.Cast();
}
}
}
这是因为
IEnumerable
没有隐式实现
IEnumerable
这在C#/.NET4中工作得很好。这是一个完整的编译和工作示例:

class ImplementFoo : IFoo
{
    List<Thing1> m_things;

    IEnumerable<IThingy> Thingies 
    {
        get
        {
            return m_things.Cast<IThingy>();
        }
    }
}
名称空间测试
{
使用制度;
使用System.Collections.Generic;
使用System.Linq;
公共接口i ingy{}
公共接口IFoo
{
IEnumerable Thingies{get;}
}
内部类Thing1:i thingy{}
内部类ImplementFoo:IFoo
{
私有列表m_things=new List(){new Thing1()};
公共数字事物
{
获取{return m_things;}
}
}
内部课程计划
{
私有静态void Main(字符串[]args)
{
var impl=new ImplementFoo();
Console.WriteLine(impl.Thingies.Count());
Console.WriteLine(“按任意键退出”);
Console.ReadKey();
}
}
}

我怀疑问题在于您的目标是.NET3.5sp1或更早版本,而不是.NET4.0。协方差只有在针对.NET4时才能正常工作,因为它需要更改新的框架。在这种情况下,.NET4中的IEnumerable实际上是,这是工作所必需的。

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

Hmmm,看看Reed的答案,然后也许我在这里给出了一个.NET 4之前的答案…这在.NET 4中确实有效。看:很好!我没有注意到这个新功能,我已经习惯于在演员名单上打电话。。。您的项目是否以.NET 4为目标?.NET 4是肯定的。让我再试一次。实际上Silverlight 4这解释了为什么它对我不起作用,我用
ICollection
Collection
进行测试。似乎ICollection不是
out T
@Anthony:
ICollection
具有将T作为输入的方法。如果你有一组香蕉,你可以把它当作一组水果,然后你可以把一个桔子放进一组香蕉里。这不应该是合法的,所以收集接口在t中不允许是协变的。@Anthony Sottile是的,这是正确的。ICollection不是4.0中的co/contra变体接口之一。@Eric现在有了意义。我想我应该考虑一下作为一个可编辑集合的含义,现在我的评论听起来很愚蠢:P@Anthony:不用担心;这些东西很难让你的大脑运转起来!
class ImplementFoo : IFoo
{
    List<Thing1> m_things;

    IEnumerable<IThingy> Thingies 
    {
        get
        {
            return m_things.Cast<IThingy>();
        }
    }
}
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();
        }
    }
}