web-dev-qa-db-ja.com

C#:IEnumerable、GetEnumerator、シンプルでシンプルな例をご覧ください!

Get enumeratorを実装するuebersimpleクラスを作成しようとしていますが、そこには単純な/機能しないサンプルがないために狂って失敗します。やりたいことは、データ構造(この場合はリストですが、後で辞書が必要になる場合があります)のラッパーを作成し、いくつかの関数を追加することです。

public class Album
{
    public readonly string Artist;
    public readonly string Title;
    public Album(string artist, string title)
    {
         Artist = artist;
         Title = title;
    } 
}
public class AlbumList
{
    private List<Album> Albums = new List<Album>;
    public Count { get { return Albums.Count; } }

    .....
    //Somehow GetEnumerator here to return Album
}

ありがとう!

27
Andrew White

List <T> .GetEnumeratorによって返される列挙子を単に返すことができます。

public class AlbumList : IEnumerable<Album>
{
    // ...

    public IEnumerator<Album> GetEnumerator()
    {
        return this.albums.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}
36
dtb

他の回答に加えて、列挙子の動作をもう少し制御する必要がある場合、または基になるデータ構造が提供できるものを超えてカスタマイズする必要がある場合は、yieldキーワードを使用できます。

public class AlbumList : IEnumerable<Album>
{
  public IEnumerator<Album> GetEnumerator()
  {
    foreach (Album item in internalStorage)
    {
      // You could use conditional checks or other statements here for a higher
      // degree of control regarding what the enumerator returns.
      yield return item;
    }
  }
}
15
Brian Gideon
using System.Collections;
using System.Collections.Generic;

public class AlbumList : IEnumerable<Album>
{
    private List<Album> Albums = new List<Album>();

    public int Count { get { return Albums.Count; } }

    public IEnumerator<Album> GetEnumerator()
    {
        return this.Albums.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

または簡易版:

public class AlbumList
{
    private List<Album> Albums = new List<Album>();

    public int Count { get { return Albums.Count; } }

    public IEnumerator<Album> GetEnumerator()
    {
        return this.Albums.GetEnumerator();
    }
}

IEnumerable<T>インターフェイスを除外することはお勧めしません。LINQを使用する可能性など、.NETとの統合が緩いためです。ただし、C#でforeachを使用してコレクションを反復処理できます。

または、これはさらに短いです:-)

public class AlbumList : List<Album>
{
}

もちろん、この最後のリストは変更可能なリストであり、おそらくあなたが望んでいるものとはまったく異なります。

9
Steven

データ構造(リスト)のラッパー、およびAlbumを返す列挙関数を使用するというコメントに基づいて、インデクサープロパティについて話していると思いますか?これがあなたのやり方です:

public class Album
{
    public readonly string Artist;
    public readonly string Title;
    public Album(string artist, string title)
    {
         Artist = artist;
         Title = title;
    } 
}

public class AlbumList
{
    private List<Album> Albums = new List<Album>();
    public int Count
    {
        get { return Albums.Count; }
    }

    public Album this[int index]
    {
        get
        {
            return Albums[index];
        }
    }

    public Album this[string albumName]
    {
        get
        {
            return Albums.FirstOrDefault(c => c.Title == albumName);
        }
    }

    public void Add(Album album)
    {
        Albums.Add(album);
    }

    public void Remove(Album album)
    {
        Albums.Remove(album);
    }
}

小さなコンソールプログラム:

        AlbumList albums = new AlbumList();
        albums.Add(new Album { Artist = "artist1", Title = "title1" });
        albums.Add(new Album { Artist = "artist2", Title = "title2" });

        for (int i = 0; i < albums.Count; i++)
        {
            Console.WriteLine(albums[i].Artist);
            Console.WriteLine(albums[i].Title);
        }

        Console.WriteLine("title for artist1");
        Console.WriteLine(albums["artist1"].Title);
2
code4life