1

質問したいのですが、列挙型を返すセレクターしかないのはなぜですか? たとえば、次のように、配列の各値を変更する必要がある場合がよくあります。

int[] a = {1,2,3,4,5};
a = a.Select(x=>x*2).ToArray();

したがって、ここでは列挙可能なものを取得し、その後でのみ配列に戻すことができます。ソースを変更できる場合に限り、Array.ForEach の使用を試みることができます。しかし、参照型の配列があり、それらを変更できない場合は、とにかく次のように書く必要があります

SomeClass[] a = FillSomeClassArray();
SomeClass[] b = a.Select(x=> ((SomeClass)x.Clone()).Modify()).ToArray();

私の場合、私は自分のクラスを使用しています

public static class CollectionHelper
{
    public static TResult[] SelectToArray<T, TResult>(this ICollection<T> source, Func<T, TResult> selector)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        if (selector == null)
            throw new ArgumentNullException("selector");
        var result = new TResult[source.Count];
        int i = 0;
        foreach (T t in source)
        {
            result[i] = selector(t);
            i++;
        }
        return result;
    }
}

ここでは、二重変換はありません。述語がない場合は、結果の長さがわかっているので、この情報を使用する必要があります。MSが私の代わりにすべての作業を行うべきではないことはわかっていますが、機能標準としては十分です。

4

1 に答える 1

1

フレームワークに追加する際の最大の問題SelectToArrayは一貫性です。を追加する場合SelectToArrayは、次のそれぞれも追加する必要があります。

  • CastToArray<T>
  • ConcatToArray<T>
  • RepeatToArray<T>
  • ReverseToArray<T>
  • SkipToArray<T>
  • OfTypeToArray<T>
  • TakeToArray<T>

新しいメソッドを追加するというテーマに取り組んでいますが、同じ最適化をリストに追加することの何が悪いのでしょうか? 今、私たちも必要です

  • SelectToList<T>(すべての始まりに似ている)
  • CastToList<T>
  • ConcatToList<T>
  • ... など - きっとお分かりでしょう。

ターゲット配列またはターゲットリストのサイズを知ることによるわずかな節約を考えると、そのような大規模なリファクタリングは非現実的です。次のような簡単な方法で同じ効果を得ることができます。

static T[] CopyToArray(
    this IEnumerable<T> source
,   T[] result
,   int pos = 0
,   int? lengthOrNull = null
) {
    int length = lengthOrNull ?? result.Length;
    foreach (var item in source) {
        if (pos > length) break;
        result[pos++] = item;
    }
    return result;
}

これで、呼び出し元は既存の LINQ 機能をこのメソッドと組み合わせて、上記のすべてのメソッドを次のように構成できますXyzToArray

IList<MyClass> data = ...
int[] res = data.Select(x => x.IntProperty).CopyToArray(new int[data.Count]);

次のように、LINQ クエリの結果を既存の配列のさまざまな部分に書き込むこともできます。

IList<MyClass> data1 = ...
IList<MyClass> data2 = ...
int[] res = new int[data1.Count+data2.Count];
data1.Select(x => x.IntProperty).CopyToArray(res, 0, data1.Count);
data2.Select(x => x.IntProperty).CopyToArray(res, data1.Count, data2.Count);
于 2013-11-10T12:09:32.337 に答える