c# – Contravariance和Entity Framework 4.0:如何将EntityCollection指定为IEnumerable?

前端之家收集整理的这篇文章主要介绍了c# – Contravariance和Entity Framework 4.0:如何将EntityCollection指定为IEnumerable?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经指定了几个接口,我使用Entity Framework 4实现了实体.我能想到的最简单的演示代码是:
public class ConcreteContainer : IContainer
{
    public EntityCollection<ConcreteChild> Children { get; set; }           
}
public class ConcreteChild : IChild
{
}
public interface IContainer
{
    IEnumerable<IChild> Children { get; set; }
}
public interface IChild
{        
}

我从上面收到以下编译器错误

‘Demo.ConcreteContainer’ does
not implement interface member
‘Demo.IContainer.Children’.
‘Demo.ConcreteContainer.Children’
cannot implement
‘Demo.IContainer.Children’
because it does not have the matching
return type of
‘System.Collections.Generic.IEnumerable’

我目前的理解是,这是因为IEnumerable(由EntityCollection实现)是协变的,但可能不是逆变的:

This type parameter is covariant. That is,you can use
either the type you specified or any type that is more
derived. For more information about covariance and contravariance,
see Covariance and Contravariance in Generics.

我是否正确,&如果是这样,有什么方法可以实现我的目标,纯粹根据其他接口而不是使用具体类来指定IContainer接口?

或者,我是否误解了一些更基本的东西?

解决方法

.NET 4中的泛型差异在这里无关紧要.接口的实现必须在类型方面完全匹配接口签名.

例如,采用ICloneable,如下所示:

public interface ICloneable
{
    object Clone();
}

能够像这样实现它会很好:

public class Banana : ICloneable
{
    public Banana Clone() // Fails: this doesn't implement the interface
    {
        ...
    }
}

…但.NET不允许这样做.您有时可以使用显式接口实现来解决此问题,如下所示:

public class Banana : ICloneable
{
    public Banana Clone()
    {
        ...
    }

    object ICloneable.Clone()
    {
        return Clone(); // Delegate to the more strongly-typed method
    }
}

但是,在你的情况下,你不能这样做.请考虑以下代码,如果认为ConcreteContainer实现IContainer,则该代码有效:

IContainer foo = new ConcreteContainer();
foo.Children = new List<IChild>();

现在你的属性设置器实际上只被声明为与EntityCollection< ConcreteChild>一起使用,所以它显然不适用于任何IEnumerable< IChild> – 违反界面.

猜你在找的C#相关文章