11

これはおそらく単純な構文の質問ですが、私にはわかりません。

通常、私はこれを行います:

public class OrderBook : IEnumerable<PriceLevel>
{
    private readonly List<PriceLevel> PriceLevels = new List<PriceLevel>();

    public IEnumerator<PriceLevel> GetEnumerator()
    {
        return PriceLevels.GetEnumerator();
    }

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

しかし、リストの代わりに、次のように配列を使用したい:

public class ArrayOrderBook : IEnumerable<PriceLevel>
{
    private PriceLevel[] PriceLevels = new PriceLevel[500];

    public IEnumerator<PriceLevel> GetEnumerator()
    {
        return PriceLevels.GetEnumerator();
    }

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

IEnumerator IEnumerable.GetEnumerator()問題なくコンパイルできるようですが、IEnumerator<PriceLevel>何らかのキャストが必要であると一般に言われています。これを行う最善の方法は何ですか?

ウィリアム

4

4 に答える 4

14

これを試して:

public class ArrayOrderBook : IEnumerable<PriceLevel>
{
    private PriceLevel[] PriceLevels = new PriceLevel[500];

    public IEnumerator<PriceLevel> GetEnumerator()
    {
        return PriceLevels.AsEnumerable().GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return PriceLevels.GetEnumerator();
    }
}
于 2012-07-03T20:41:33.850 に答える
6

独自の実装からわかるようIEnumerable<T>に、インターフェイスを満たすには、メソッドの汎用バージョンと非汎用バージョンの両方を提供する必要があります。これを行うには、メソッドが同じシグネチャを持っているため、そのうちの1つが明示的なインターフェイス実装である必要があります。の場合List、ジェネリックバージョンはクラス内のメソッドであり、非ジェネリックバージョンは明示的なインターフェイス定義です。これは、ジェネリックバージョンの方が一般的に便利だからです。配列の場合、実装としてすでに非ジェネリックバージョンがあり、後続のバージョンでメソッドのジェネリックバージョンが追加されていました。重大な変更を回避するために、代わりに汎用バージョンが明示的なインターフェース定義になります。

この問題を解決するには、いくつかの方法があります。これが3つの簡単なものです。

public IEnumerator<PriceLevel> GetEnumerator()
{
    return PriceLevels.AsEnumerable().GetEnumerator();
}


public IEnumerator<PriceLevel> GetEnumerator()
{
    IEnumerable<PriceLevel> enumerator = PriceLevels;
    return enumerator.GetEnumerator();
}

public IEnumerator<PriceLevel> GetEnumerator()
{
    return ((IEnumerable<PriceLevel>)PriceLevels).GetEnumerator()
}
于 2012-07-03T20:43:09.923 に答える
4

T[]対応するキャストIEnumerable<T>

    public IEnumerator<PriceLevel> GetEnumerator()
    {
        return ((IEnumerable<PriceLevel>)PriceLevels).GetEnumerator();
    }
于 2012-07-03T20:43:57.360 に答える
2

ECMA-335パーティションI、§8.9.1によると、ベクトル型(のよ​​うな一次元配列T[])が実装されます。IList<T>これは、も実装することを意味しますIEnumerable<T>。ただし、メソッドの実装は明示的であるため、次のいずれかを使用する必要があります。

オプション1:配列の暗黙的な割り当てを使用するだけIList<T>です。

private IList<PriceLevel> PriceLevels = new PriceLevel[500];

オプション2:メンバー変数を配列のままにし、AsEnumerable拡張メソッドを使用します。この拡張メソッドは、サポートされている暗黙の割り当てを使用します。これは、のような直接キャストを使用するよりも望ましい方法(IEnumerable<PriceLevel>)PriceLevelsです。

IEnumerator IEnumerable.GetEnumerator()  
{  
    return PriceLevels.AsEnumerable().GetEnumerator();  
}  

避けるべき項目:

  1. このCast<T>メソッドでは、配列の各要素に不要な型チェックが導入されるため、回避する必要があります。
  2. 列挙からnull以外の要素のみを含める必要がある場合は、OfType<T>extensionメソッドを使用しても問題ありません。それ以外の場合、このメソッドでは、各要素に不要な型チェックが導入されます。
于 2012-07-03T20:59:46.340 に答える