实现c#字典会导致错误:没有匹配的返回类型

本文关键字:返回类型 错误 字典 实现 | 更新日期: 2023-09-27 18:14:15

我想了解c#是如何实现字典的。在我看来,字典应该继承IEnumerable,这需要方法实现:

IEnumerable GetEnumerator()
然而,c# Dictionary实现了:
Dictionary<T>.Enumerator GetEnumerator()

其中Enumerator是继承IEnumerator的嵌套结构体。

我已经创建了一个这种关系的例子:

public interface IFoo
{
    IFoo GetFoo();
}
public abstract class Foo : IFoo
{
    public abstract FooInternal GetFoo();
    public struct FooInternal : IFoo
    {
        public IFoo GetFoo()
        {
            return null;
        }
    }
}

但是,这不会编译,导致以下错误:

Error   2   'Foo' does not implement interface member 'IFoo.GetFoo()'. 'Foo.GetFoo()' cannot implement 'IFoo.GetFoo()' because it does not have the matching return type of 'CodeGenerator.UnitTests.IFoo'. Foo.cs  14

有什么想法我可能做错了吗?c#是如何实现字典的?如何使示例代码编译类似于c#字典?

实现c#字典会导致错误:没有匹配的返回类型

您缺少一个显式接口实现:

public abstract class Foo : IFoo
{
    public abstract FooInternal GetFoo();
    // start here
    IFoo IFoo.GetFoo()
    {
        return GetFoo();
    }
    // end here
    public struct FooInternal : IFoo
    {
        public IFoo GetFoo()
        {
            return null;
        }
    }
}

你混淆了两个不同的接口,即 IEnumerableIEnumerator

外部类,字典类,实现IEnumerable。这涉及到外部类有一个方法GetEnumerator。这个方法返回一个嵌套(内部)结构体的实例。

内部结构实现IEnumerator。要实现IEnumerator,你必须有一个MoveNext方法和一个Current属性。

此外,还有显式接口实现的问题,Andrey Shchekin的回答中也提到了这个问题。这段代码是合法的,类似于Dictionary<,>:

public interface IFoo   // corresponds to IEnumerable
{
  IBar GetBar();
}
public interface IBar   // corresponds to IEnumerator
{
}

public class Foo : IFoo
{
  // public method that has BarInternal as return type
  public BarInternal GetBar()
  {
    return new BarInternal();
  }
  // explicit interface implementation which calls the public method above
  IBar IFoo.GetBar()
  {
    return GetBar();
  }
  public struct BarInternal : IBar
  {
  }
}

也可以通过公共方法"直接"(而不是显式)实现IFoo,但是声明的返回类型必须匹配:

public class Foo : IFoo
{
  // public method that directly implements the interface
  public IBar GetBar()
  {
    return new BarInternal();
  }
  public struct BarInternal : IBar
  {
  }
}

Dictionary<,>没有以这种更简单的方式编写的原因,我猜是您对嵌套结构进行了装箱。

请注意,当您使用foreach通过Dictionary<,>时,c#编译器首先搜索具有确切名称GetEnumerator的公共非泛型无参数实例方法。如果找到这样的方法,就使用它,编译器不关心IEnumerable。因此,对于Dictionary<,>,在foreach期间使用稍微更优的公共方法,该方法不实现接口。

在MSDN上记录了显式接口实现。参见Dictionary<TKey, TValue>.IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator(通用)和Dictionary<TKey, TValue>.IEnumerable.GetEnumerator(非通用)