【问题标题】:Cannot implement interface member because it does not have the matching return type of List<IInterface>无法实现接口成员,因为它没有匹配的返回类型 List<IInterface>
【发布时间】:2012-08-14 15:22:19
【问题描述】:

我有接口IChildIParentIParent 有一个成员是 List&lt;IChild&gt;

我希望有实现IParent 的类,其中每个类都有一个实现IChild 的成员:

public interface IChild
{ 
}  

public interface IParent
{  
    List<IChild> a { get; set; }
} 

public class ChildA : IChild
{ 
} 

public class ChildB : IChild
{ 
} 

public class ParentA : IParent
{ 
    public List<ChildA> a { get; set; }
}

public class ParentB : IParent
{ 
    public List<ChildB> a { get; set; }
}

但是,这段代码不会编译。错误是:

`MyApp.Data.ParentA` does not implement interface member `MyApp.Data.IParent.a`.
`MyApp.Data.ParentA.a` cannot implement `MyApp.Data.IParent.a` because it does not have
the matching return type of `System.Collections.Generic.List<MyApp.Data.IChild>`.

【问题讨论】:

  • List 属性声明为ILists 会更明智,它们的限制性较小,但提供相同的功能。不过对这个问题没有帮助。
  • 那么他就可以做到IEnumerable。这可能不是要求
  • @Jodrell IList 不提供与List 相同的功能。
  • @Suncat2000,你是对的,但是,IListICollection(他们的只读对应物)或IEnumerable 可能是一个较小的承诺,可以满足所需的功能级别。跨度>

标签: c# generics inheritance interface


【解决方案1】:

使 IParent 通用:

public interface IChild
{
}

public interface IParent<TChild> where TChild : IChild
{
    List<TChild> a { get; set; } 
}

public class ChildA : IChild {  }   

public class ChildB : IChild {  }   

public class ParentA : IParent<ChildA>
{
    public List<ChildA> a { get; set; }
}

public class ParentB : IParent<ChildB>
{
    public List<ChildB> a { get; set; }
}

【讨论】:

  • 我真希望我能投票 100 次...这是一个案例研究,说明为什么泛型如此有用。
  • 您能否详细说明解决方案背后的原理?
【解决方案2】:

实现只能返回 IChild 的 List 如下:

public interface IChild
{
}

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

public class ChildA : IChild
{
}

public class ChildB : IChild
{
}

public class ParentA : IParent
{

    public List<IChild> Children
    {
        get;
        set;

    }
}

public class ParentB : IParent
{
    public List<IChild> Children
    {
        get;
        set;
    }
}

【讨论】:

    【解决方案3】:

    您需要让类返回List&lt;IChild&gt;

    public class ParentA : IParent
    { 
        public List<IChild> a { get; set; }
    }
    
    public class ParentB : IParent
    { 
        public List<IChild> a { get; set; }
    }
    

    【讨论】:

    • 不知道为什么这被赞成。这不会编译。您无法将 List&lt;ChildX&gt; 转换为 List&lt;IChild&gt; 或从 List&lt;IChild&gt; 转换。
    【解决方案4】:

    IChild 的集合不能隐式转换为其子类型的集合

    IParent.a的返回类型更改为List&lt;ChildA&gt;ParentAParentB的属性声明更改为public List&lt;IChild&gt; a { get; set; }。我推荐后者,因为我认为这是您最可能想要的。

    【讨论】:

    • 您的意思是,更改ParentAParentB 上的属性声明? IParent 上的那个已经是 List&lt;IChild&gt;
    • 是的,您必须更改实现类的声明。
    【解决方案5】:

    我有一个类似的需求,我有两个不同的方法,它们对两个不同的类进行操作,但对于两个类共有的属性具有相同的逻辑。

    所以我想用继承和泛型为此写一个通用的方法,我可以通过以下方式实现。

    namespace OOPS.Interfaces
    {
        using System.Collections.Generic;
    
        public interface IBanner
        {
            string Name { get; set; }
        }
    
        public interface IBannerContent<T> where T : IBanner
        {
            List<T> Banners { get; set; }
        }
    }
    

    简单模型。

    namespace OOPS.Simple
    {
        using Interfaces;
        using System.Collections.Generic;
    
        public class Banner : IBanner
        {
            public string Name { get; set; }
        }
    
        public class BannerContent : IBannerContent<Banner>
        {
            public List<Banner> Banners { get; set; }
        }
    }
    

    复杂模型。

    namespace OOPS.Complex
    {
        using Interfaces;
        using System.Collections.Generic;
    
        public class Banner : IBanner
        {
            public string Name { get; set; }
    
            public string Description { get; set; }
        }
    
        public class BannerContent : IBannerContent<Banner>
        {
            public List<Banner> Banners { get; set; }
        }
    }
    

    常见的业务逻辑和示例调用。这里的关键部分是使用where 子句将where T : IBanner 等类型一直约束到我们希望它通用的方法。

    namespace OOPS
    {
        using Interfaces;
        using System;
        using System.Collections.Generic;
    
        public class BusinessLogic
        {
            public void Print<T>(IBannerContent<T> bannerContent) where T : IBanner
            {
                foreach (var item in bannerContent.Banners)
                {
                    Console.WriteLine(item.Name);
                }
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                var banner1 = new Simple.BannerContent
                {
                    Banners = new List<Simple.Banner>
                    {
                        new Simple.Banner { Name = "Banner 1" },
                        new Simple.Banner { Name = "Banner 2" }
                    }
                };
    
                var banner2 = new Complex.BannerContent
                {
                    Banners = new List<Complex.Banner>
                    {
                        new Complex.Banner { Name = "Banner 3", Description = "Test Banner" },
                        new Complex.Banner { Name = "Banner 4", Description = "Design Banner" }
                    }
                };
    
                var business = new BusinessLogic();
                business.Print(banner1);
                business.Print(banner2);
                Console.ReadLine();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      相关资源
      最近更新 更多