6

Get next N elements from enumerableに質問する答えを探していましたが、満足のいくものが見つからず、自分で作成しました。私が思いついたのは

IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n, Func<IEnumerable<R>, T> action){
  IEnumerable<R> head;
  IEnumerable<R> tail = src;
  while (tail.Any())
  {
    head = tail.Take(n);
    tail = tail.Skip(n);
    yield return action(head);
  }
}

私が本当に欲しいのは、 action のデフォルトをt=>tにすることですが、それをデフォルトの引数にする方法がわかりません。署名IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n, Func<IEnumerable<R>, T> action = t=>t)で構文エラーが発生します。

私の質問は、どうすればいいですか?

これはラムダ関数をデフォルト引数として指定するのと同じだと思いますが、C++ ではなく C# の場合です。

補足として、構文上の違いはないことはわかっていますが、切り替えた場合は読みやすくなりTますRか?

4

2 に答える 2

13

デフォルト値は定数である必要があり、デリゲートの唯一の定数値はnull参照です。

代わりにオーバーロードを使用することをお勧めします。からへt => tの変換があることを知っていない限り、とにかく有効ではないことに注意してください。これはどこにもありません。IEnumerable<R>T

ラムダ式の有効性の問題は別として、null 合体演算子を使用できます。

IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n,
                           Func<IEnumerable<R>, T> action = null)
{
    action = action ?? (t => t);
    ...
}

...しかし、それはそれを悪用するようなものであり、 が null 以外の値を渡していると思っていた呼び出し元からのものであるどうかを判断することはできずnull、.ArgumentNullException

編集:さらに、あなたの方法は根本的に問題があることに注意してください-チャンクを反復すると、適切な量をスキップするために元のシーケンスが数回(チャンクごとに1回)評価されます。返す前に各チャンクを積極的に読み取るメソッドを作成する方がよいでしょう。と呼ばれるMoreLINQに同様のメソッドがありBatchます。Batchここで言及されているオーバーロードが正確に含まれていることに注意してください。この場合、オーバーt => tロードの型パラメーターが少ないため機能し、ID 変換が問題ないことがわかります。

于 2012-06-21T14:28:24.887 に答える
2

C# の場合も同じです: オーバーロードを作成します。

IEnumerable<T> Chunk<T, R>(IEnumerable<R> src, int n){
    return Chunk<T, R>(src, n, t => t);
}
于 2012-06-21T14:29:10.283 に答える