7

を実装するクラスがありますIEnumerator<string>。下記参照:

public class MyClass : IEnumerator<string>
{
    public bool MoveNext()
    {
        //....
    }

    //Implement other required methods....

   //Confusion lies below:
   public string Current { get { return this.CurrentLine; } }

   //Why do I need to implement IEnumerator.Current?!  In my tests, it's not even called    during my iteration
   object IEnumerator.Current { get { throw new NotImplementedException(); } }

}   

IEnumerator<T>.CurrentプロパティがインターフェイスとIEnumeratorIEnumerator<T>継承する)インターフェイスの両方に存在するという事実に加えて、それを実装するポイントは何ですか?上で見たように、それは呼ばれることさえありません。

4

3 に答える 3

17

IEnumerator<T>を実装IEnumeratorするため、最も基本的なレベルでは、契約を履行する必要があります。

具体的には、理由について-誰かがこれを行うとどうなりますか?

((IEnumerator)yourInstance).Current

IEnumerator<T>彼らは(通常)の実装から返された同じ値/参照の緩く型付けされたコピーを取得することを期待する必要があります。したがって、ほとんどの場合、戻っthis.Currentて心配する必要はありません:)

(FYI- this.CurrentDRYとSRPに従うため、戻ることも良い習慣です-強く型付けされたバージョンのCurrentに、Currentが実際に何であるかの実装の詳細を処理させます。)

于 2011-03-02T18:56:27.407 に答える
3

その理由は、 がIEnumerator<T>継承するIEnumeratorためです。継承IEnumerator<T>すると、暗黙的に も継承し IEnumeratorます。インターフェイスをアドバタイズする場合は、使用するつもりがなくても、そのインターフェイスの実装も提供する必要があります。

于 2011-03-02T18:58:08.450 に答える
1

コンパイラは、未知の将来のある時点で予期しないアセンブリがアセンブリをロードするときにどの仮想が呼び出されるかを知ることができないため、すべての仮想を実装する必要があります。インターフェイスから継承することにより、すべてのメンバーを実装することを約束する「契約に署名」しています。コンパイラは、他のアセンブリがそれに依存できるように、その合意を保持します。

インターフェイス機能の目的は、クラスが他のアセンブリに、いつでも、どこでも、「これは私に依頼できることです」と伝えることができるようにすることです。より少ない機能を宣伝したい場合は、必要な部分的な機能のみを提供する新しいインターフェイスを定義し、代わりにそれを実装します。

もちろん、これはすべて産業用強度のものです。それは、今あなたのコードに必要以上のものです。しかし、C# はおもちゃだけでなく、本格的な作業にも役立つように設計されています。

2 つの異なるほぼ同一のオーバーライドについては、両方の Current プロパティをオーバーライドする必要があります。これらは本質的に異なるためです。1 つは T を返すジェネリックです。もう 1 つは非ジェネリックな戻りオブジェクトです。String 参照を Object への参照としていつでも扱うことができますが、それは両方の方法ではありません。では、値型についてはどうでしょうか。T はクラスに制約されません。確かに、コンパイラは仮説的にこれらすべてを把握し、2 つが代替可能である場合に問題を解決することができますが、そうではなく、そうすべきだとは確信していません。C++ が必要な場合は、その場所を知っています。

于 2011-03-02T19:04:07.253 に答える