【问题标题】:Interface design implementation error: ... cannot implement ... because it does not have a matching return type接口设计实现错误:...无法实现...因为它没有匹配的返回类型
【发布时间】:2013-12-17 02:01:27
【问题描述】:

我在 Library1 中有几个类:上面的类使用的 A 类、B 类等。

public class A 
{  
    int VarA1;  
}

public class B
{  
    List<A> SetA {get; set; }
    void MethodB1()
    {
            ...
            this.SetA = new List<A>;
            ...
    }
}

现在我想为那个 Library1 提供一个接口,这样就可以有其他的实现了。调用接口库ILibrary:

public interface IA
{  
    int VarA1 {get; set; }  
}

public interface IB
{  
    List<IA> SetA { get; set; }
    void MethodB1();
}

Library1 中正在实现的功能:

public class A : IA
{  
    int VarA1{ get; set; }  
}

public class B : IB
{  
    List<IA> SetA {get; set; }
    void MethodB1()
    {
            ...
            this.SetA = new List<A>;
            ...
    }
}

但是我收到了这段代码的编译错误:

Library1.B.SetA 无法实现 ILibrary.IB.SetA,因为它没有匹配的返回类型。

我也试过了:

public class B : IB
{  
    List<A> SetA {get; set; }
    void MethodB1()
    {
            ...
            this.SetA = new List<A>;
            ...
    }
}

但这并没有解决问题(同样的错误消息)。为什么会出现此错误,我该如何解决?

【问题讨论】:

  • 添加了更多详细信息,因此问题复制了我面临的问题。
  • 问题还是一样。为了符合接口,返回的参数类型必须与接口中声明的内容完全匹配。请参阅我的更新答案。
  • 您的代码仍然包含几个错误,并且绝对无法复制您所描述的问题。接口不能有字段:public interface IA { int VarA1; } 是不可能的。你在 SetA 和 ASet 之间切换了几次
  • @HugoRune 感谢 cmets。我更正了我的代码。

标签: c# class interface


【解决方案1】:

如错误信息所示,为了符合接口,B.MethodB1 必须返回IA 类型,如下所示:

public class B : IB
{  
    public IA MethodB1() { ... }  
}

另一种方法是将IB 声明为这样的通用接口:

public interface IB<out T> where T : IA
{  
    public T MethodB1();  
}

然后B 像这样:

public class B : IB<A>
{  
    public A MethodB1() { ... }  
}

关于您更新的问题,您的问题仍然是相同的,解决方案也是如此。要么做这样的事情:

public class B : IB
{  
    public List<IA> SetA {get; set; }
    public void MethodB1()
    {
            ...
            this.SetA = new List<IA>();
            ...
    }
}

或者像这样:

public interface IB<T> where T : IA
{  
    List<T> SetA { get; set; }
    void MethodB1();
}

public class B : IB<A>
{  
    public List<A> SetA {get; set; }
    public void MethodB1()
    {
            ...
            this.SetA = new List<A>();
            ...
    }
}

【讨论】:

    【解决方案2】:

    接口中方法的实现必须返回完全相同的类型,而 IA 与 A 不同。它们必须绝对匹配,所以它必须返回 IA。但是,您的 MethodB1 的 B 实现没有主体,并且该类不是抽象的,因此您仍然会收到错误。

    【讨论】:

      【解决方案3】:

      List&lt;A&gt; 不继承或实现List&lt;IA&gt;

      接口 IB 需要 List&lt;IA&gt; 属性。 B 类有一个List&lt;A&gt; 属性。

      考虑:

      interface IAnimal()
      {
        public void HaveLunch();
      }
      
      class Zebra:IAnimal
      class Lion:IAnimal
      
      
      interface IZoo
      {
        List<IAnimal> Zebras {get;set;}
        List<IAnimal> Lions {get;set;}
      }
      
      public class Zoo
        : IZoo //does not work
      {
        List<Zebra> Zebras {get;set;}
        List<Lion> Lions {get;set;}
      }
      
      
      //...
      IZoo myZoo = new Zoo;
      myZoo.Zebras.Add(new Lion());  //because of this.
      

      【讨论】:

        【解决方案4】:

        其他答案已经说了为什么这不起作用:

        • 继承的属性必须使用与父属性完全相同的类型
        • 你不能分配List&lt;IA&gt; myList = new List&lt;A&gt;();
          您必须使用相同的类型。这是因为 List 不是协变的。

        因此,您必须在整个代码中使用 IA 而不是 A,并且只能使用 IA 可访问的公共方法

        但是,如果您将 ASet 的类型更改为 IEnumerable&lt;IA&gt;,则有一种方法可以使其工作,同时仍然可以访问 A:

        • 你可以分配IEnumerable&lt;IA&gt; myList = new List&lt;A&gt;();
          因为 IEnumerable supports covariance,从 C# 4.0 开始

        IEnumerable 不支持 List 支持的所有方法,例如,您不能向 IEnumerable 添加更多元素。不幸的是,这对于使协方差起作用是必要的。但是,您可以在 B 类内部使用 List,并且只将 IEnumerable 呈现给外部。

        public interface IB
        {  
            IEnumerable<IA> SetA { get; set; }
            void MethodB1();
        }
        
        public class B : IB
        {  
            private List<A> listA;
        
            public IEnumerable<IA> SetA 
            {
                get {return listA;} 
                set {throw new NotImplementedException();} 
                // the setter is somewhat inelegant, 
                // if you do not need the setter 
                // you should probably leave it out of the interface entirely
            }
        
            public void MethodB1()
            {
                    this.listA = new List<A>()
            }
        }
        

        【讨论】:

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