c#卡在泛型和接口上

c#卡在泛型和接口上,c#,generics,interface,C#,Generics,Interface,我不明白为什么下面的代码在c#(.NETCore1.1)中不起作用 公共接口IChild { } 公共接口IParent { IEnumerable子项{get;set;} } 公共抽象类ParentBase:IParent 孩子们:IChild { 公共IEnumerable子项{get;set;} } 错误消息是 错误CS0738“ParentBase”未实现接口成员“IParent.Children”ParentBase.Children'无法实现'IParent.Children',因

我不明白为什么下面的代码在c#(.NETCore1.1)中不起作用

公共接口IChild
{
}
公共接口IParent
{
IEnumerable子项{get;set;}
}
公共抽象类ParentBase:IParent
孩子们:IChild
{
公共IEnumerable子项{get;set;}
}
错误消息是

错误CS0738“ParentBase”未实现接口成员“IParent.Children”ParentBase.Children'无法实现'IParent.Children',因为它没有匹配的返回类型'IEnumerable'

错误消息表示IEnumerable不是IEnumerable类型,而我将TChild约束为IChild

我找到了两种“简单”的解决方法,但这两种方法都需要对客户端代码进行相当糟糕的更改。我使用客户机代码中的ConfigurationSection.Bind()加载这些类型的整个对象树

不需要的解决方案1:使父接口通用

public interface IChild
{
}

public interface IParent<TChild>
    where TChild : IChild
{
    IEnumerable<TChild> Children { get; set; }
}

public abstract class ParentBas<TChild> : IParent<TChild>
    where TChild : IChild
{
    public IEnumerable<TChild> Children {get; set; }
}
公共接口IChild
{
}
公共接口IParent
孩子们:IChild
{
IEnumerable子项{get;set;}
}
公共抽象类ParentBas:IParent
孩子们:IChild
{
公共IEnumerable子项{get;set;}
}
不需要的解决方案2:

public interface IChild
{
}

public interface IParent
{
    IEnumerable<IChild> Children { get; set; }
}

public abstract class ParentBas<TChild> : IParent
    where TChild : IChild
{
    public IEnumerable<IChild> Children {get; set; }
}
公共接口IChild
{
}
公共接口IParent
{
IEnumerable子项{get;set;}
}
公共抽象类ParentBas:IParent
孩子们:IChild
{
公共IEnumerable子项{get;set;}
}

这不起作用的原因很简单:

public interface Animal { }

public interface ICage
{
   IEnumerable<IAnimal> Animals { get; set; }
}

public class Cage<TAnimal> where Animal: Animal
{
    public IEnumerable<TAnimal> { get; set; } //Illegal implementation of ICage
}

因此,您显然可以看到为什么您的代码根本不符合
IParent
的约定。

为什么使用generic
ParentBas
?您不需要它-
IEnumerable Children
已经接受了所有的
IChild
实现?“我不明白为什么下面的代码在c#中不起作用”-因为这会导致接口和具体类之间的不一致,例如允许通过interfaceWell将一个dog child添加到cat父类中,ParentBas拼写错误,应该是ParentBase。拥有抽象父基类的目的是为其中的父类实现公共功能。为了清楚起见,我删除了那个常见的代码。您的问题与堆栈溢出中的所有其他问题完全一样,混淆了类型继承和类型参数继承。请参阅标记的副本以获得更好的解释。对不起,我一点也不清楚。如果dogCage属于Cage类型,那么在这两个示例中,将猫添加到动物列表中都是非法的。仍然不明白为什么我对IParent、IChild和ParentBase的声明是非法的。@StefaanVandevelde很好,因为接口
iAge
声明它允许任何
IEnumerable
,包括
IEnumerable
。在您的提案中,
Cage
只允许
IEnumerable
s。这违反了
ICage
@StefaanVandevelde的约定,这正是重点,您的接口不允许任何东西,无论实现类的泛型类型是什么,任何
IAnimal
都是有效的。为什么界面要担心TAnimal的问题?它对此一无所知……好吧,是的,这是有道理的
public interface Animal { }

public interface ICage
{
   IEnumerable<IAnimal> Animals { get; set; }
}

public class Cage<TAnimal> where Animal: Animal
{
    public IEnumerable<TAnimal> { get; set; } //Illegal implementation of ICage
}
var dogCage = new Cage<Dog>();
dogCage.Animals = new[] { cat }; //Illegal! Why?!?
ICage dogCage = new Cage<Dog>();
dogCage.Animals = new[] { cat }; //Legal!