2

Iterator パターンを実装しようとしています。基本的に、私が理解していることから、クラスを「foreachble」にし、正確なコレクションタイプをユーザーに公開しないことでコードをより安全にします。

私は少し実験してきましたが、クラスに IEnumerator GetEnumerator() を実装すると、目的の結果が得られることがわかりました...インターフェイスの実現をいじるという頭痛の種がないように見えます。

ここに私が意味することを垣間見ることができます:

public class ListUserLoggedIn
{
    /*
        stuff
    */
    
    public List<UserLoggedIn> UserList { get; set; }

    public IEnumerator<UserLoggedIn> GetEnumerator()
    {
        foreach (UserLoggedIn user in this.UserList)
        {
            yield return user;
        }
    }

    public void traverse()
    {
        foreach (var item in ListUserLoggedIn.Instance)
        {
            Console.Write(item.Id);
        }
    }
}

私の質問は、これは Iterator の有効な例ですか? はいの場合、なぜこれが機能するのですか。イテレータが「var」を介して一部または匿名オブジェクトのみを返すようにするにはどうすればよいですか。そうでない場合、正しい方法は何ですか...

4

1 に答える 1

5

まず、より小さく単純化された自己完結型のバージョン:

class Program
{
    public IEnumerator<int> GetEnumerator()  // IEnumerable<int> works too.
    {
        for (int i = 0; i < 5; i++)     
            yield return i;     
    }

    static void Main(string[] args)
    {
        var p = new Program();

        foreach (int x in p)
        {
            Console.WriteLine(x);
        }
    }
}

そして、ここでの「奇妙な」ことは、それclass Programが実装されていないことIEnumerableです。

Ecma-334 の仕様は次のように述べています。

§ 8.18 イテレータ
foreach ステートメントは、列挙可能なコレクションの要素を反復処理するために使用されます。列挙可能にするために、コレクションには、列挙子を返すパラメーターなしの GetEnumerator メソッドが必要です。

foreach()それがあなたのクラスで動作する理由です。IEnumerable については言及されていません。しかし、GetEnumerator() はどのようにしてCurrentandを実装するものを生成するのMoveNextでしょうか? 同じセクションから:

イテレータは、順序付けられた一連の値を生成するステートメント ブロックです。イテレータは、1 つ以上の yield ステートメントの存在によって通常のステートメント ブロックと区別されます。

イテレータは一種のメンバーではなく、関数メンバーを実装する手段であることを理解することが重要です

したがって、メソッドの本体は反復子ブロックであり、コンパイラはいくつかの制約をチェックし (メソッドは IEnumerable または IEnumerator を返す必要があります)、IEnumeratorメンバーを実装します。

そして、より深い「なぜ」について、私も何かを学びました。「The C# Programming Language 3rd」の 369 ページの Eric Lippert による注釈に基づいています。

これは「パターンベースのアプローチ」と呼ばれ、ジェネリックより前にさかのぼります。C#1 のインターフェイス ベースのアプローチは、受け渡しに完全に基づいてobjectおり、値の型は常にボックス化する必要がありました。パターンアプローチにより、

foreach (int x in myIntCollection)

ジェネリックなし、ボクシングなし。きちんとした。

于 2013-08-28T22:08:42.163 に答える