0

C# がDictionaryを実装する方法を理解しようとしています。Dictionary は、次のメソッドの実装を必要とする IEnumerable から継承することになっているようです。

IEnumerable GetEnumerator()

ただし、C# ディクショナリは代わりに次を実装します。

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# は Dictionary をどのように実装しますか? サンプル コードを C# ディクショナリと同様にコンパイルするにはどうすればよいでしょうか?

4

2 に答える 2

3

明示的なインターフェイスの実装がありません:

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;
        }
    }
}
于 2013-05-17T03:44:02.173 に答える
1

IEnumerableIEnumeratorという 2 つの異なるインターフェイスを混同しています。

外側のクラスであるディクショナリ クラスは、 を実装しIEnumerableます。これには、外部クラスにメソッドがあることが含まれGetEnumeratorます。このメソッドは、ネストされた (内側の) 構造体のインスタンスを返します。

内部構造体は を実装してIEnumeratorいます。実装するには、メソッドとプロパティIEnumeratorが必要です。MoveNextCurrent

その上、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(非ジェネリック) を参照してください。

于 2013-05-17T08:28:32.177 に答える