75

IEnumerable<T>C# の多次元配列は を実装しているのに、 を実装していないことに気付きましたIEnumerable。1 次元配列の場合、IEnumerable<T>との両方IEnumerableが実装されています。

この違いはなぜですか?多次元配列が の場合IEnumerable、ジェネリック バージョンも実装する必要がありますか? 多次元配列で拡張メソッドを使用しようとしたため、これに気付きましたCast<T>。したがって、多次元配列を実装するための引数が確実にわかりますIEnumerable<T>

コードで私の質問を明確にするために、次のコードがtrue実際にはtrue, false, true, を出力している間に、4 回出力されると予想しtrueます。

int[] singleDimensionArray = new int[10];
int[,] multiDimensional = new int[10, 10];

Debug.WriteLine(singleDimensionArray is IEnumerable<int>);
Debug.WriteLine(multiDimensional is IEnumerable<int>);
Debug.WriteLine(singleDimensionArray is IEnumerable);
Debug.WriteLine(multiDimensional is IEnumerable);
4

5 に答える 5

51

CLR には 2 種類の配列があります。1 次元で下限が 0 であることが保証されているベクトルと、0 以外の境界と 0 以外のランクを持つことができるより一般的な配列です。

CLI 仕様のセクション 8.9.1 から:

さらに、要素型 T で作成されたベクトルは System.Collections.Generic.IList<U> 、U := T であるインターフェイス (§8.7) を実装します。

私にはかなり奇妙に思えると言わざるを得ません。すでに実装されていることを考えると、実装IEnumerableすべきではない理由がわかりませんIEnumerable<T>。を実装するのはあまり意味がありませんIList<T>が、単純な汎用インターフェイスで十分です。

これが必要な場合は、Cast<T>(.NET 3.5 を使用している場合) を呼び出すか、独自のメソッドを記述して配列を反復処理することができます。キャストを回避するには、各次元の下限/上限を見つけ、その方法でフェッチする独自のメソッドを作成する必要があります。ひどく快適ではありません。

于 2008-11-08T20:14:33.437 に答える
18

回避策があります。任意の多次元配列をIEnumerableに変換できます。

public static class ArrayExtensions
{
    public static IEnumerable<T> ToEnumerable<T>(this Array target)
    {
        foreach (var item in target)
            yield return (T)item;
    }
}
于 2009-07-25T21:45:42.277 に答える
7

ゼロ バウンドの 1 次元配列は と の両方IEnumerableを実装しIEnumerable<T>ますが、多次元配列は残念ながら のみを実装しIEnumerableます。@Jader Diasによる「回避策」は実際に多次元配列をに変換しますIEnumerable<T>が、莫大なコストがかかります.配列のすべての要素がボックス化されます.

これは、すべての要素に対してボクシングを行わないバージョンです:

public static class ArrayExtensions
{
    public static IEnumerable<T> ToEnumerable<T>(this T[,] target)
    {
        foreach (var item in target)
            yield return item;
    }
}
于 2017-10-29T06:02:58.260 に答える
1

IEnumerable<int>多次元構造は実際には型の配列ではなく、型の配列の配列であるため、ジャグ配列はどちらもサポートしていません。

int[] singleDimensionArray = new int[10];
int[][] multiJagged = new int[10][];

Debug.WriteLine(singleDimensionArray is IEnumerable<int>);
Debug.WriteLine(multiJagged is IEnumerable<int[]>);
Debug.WriteLine(singleDimensionArray is IEnumerable);
Debug.WriteLine(multiJagged is IEnumerable);

true、true、true、true を出力します。

:int[,]ではありません。これIEnumerable<int[]>は、他の回答で指定されている理由によるものです。つまり、反復する次元を知る一般的な方法はありません。ギザギザの配列では、配列の配列であるという構文が非常に明確であるため、解釈の余地はあまりありません。

于 2008-11-08T19:58:45.450 に答える