this のような正しい入力および出力タイプを扱う、これに似たいくつかの質問があります。私の質問は、どのようなグッド プラクティス、メソッドの命名、パラメーターの型の選択など、遅延実行事故から保護できるものですか?
これらはIEnumerable
、次の理由により、非常に一般的な引数タイプである最も一般的です。
堅牢性の原則 に従います。
で広く使用されています
Linq
IEnumerable
コレクション階層の上位にあり、新しいコレクション タイプよりも古い
ただし、遅延実行も導入されます。メソッド (特に拡張メソッド) を設計する際に、最も基本的な型を使用することが最善のアイデアであると考えていたのに、間違っていた可能性があります。したがって、メソッドは次のようになります。
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> lstObject)
{
foreach (T t in lstObject)
//some fisher-yates may be
}
明らかに危険なのは、上記の関数をレイジーLinq
と混ぜ合わせて非常に影響を受けやすいことです。
var query = foos.Select(p => p).Where(p => p).OrderBy(p => p); //doesn't execute
//but
var query = foos.Select(p => p).Where(p => p).Shuffle().OrderBy(p => p);
//the second line executes up to a point.
より大きな編集:
もう一度言いますが、言語の機能に対する批判は建設的ではありませんが、良い実践方法を求めるのは StackOverflow の強みです。これを反映するように質問を更新しました。
ここで大きな編集:
上記の行を明確にするために-私の質問は、2番目の式が評価されないことではなく、真剣に評価されないことです。プログラマーはそれを知っています。私の心配は、Shuffle
メソッドが実際にその時点までクエリを実行することです。何も実行されない最初のクエリを参照してください。同様に、別の Linq 式 (後で実行する必要があります) を構築するときに、カスタム関数が台無しになります。言い換えれば、呼び出し元に知らせる方法Shuffle
は、Linq 式のその時点で必要な関数ではありません。ポイントが家に帰ることを願っています。申し訳ありません!:)メソッドに行って検査するのと同じくらい簡単ですが、皆さんは通常どのように防御的にプログラムするのですか..
上記の例はそれほど危険ではないかもしれませんが、要点はわかります。Linq
それは、特定の (カスタム) 関数が遅延実行の考え方にうまく適合しないことです。問題はパフォーマンスだけでなく、予期しない副作用についてもです。
しかし、このような関数は魔法のように動作しLinq
ます:
public static IEnumerable<S> DistinctBy<S, T>(this IEnumerable<S> source,
Func<S, T> keySelector)
{
HashSet<T> seenKeys = new HashSet<T>(); //credits Jon Skeet
foreach (var element in source)
if (seenKeys.Add(keySelector(element)))
yield return element;
}
ご覧のとおり、両方の関数が を受け取りますIEnumerable<>
が、呼び出し元は関数がどのように反応するかを知りません。では、皆さんがここで取っている一般的な予防措置は何ですか?
Linq
カスタム メソッドに適切な名前を付けて、呼び出し元が?とうまくいくかどうかがわかるようにします。遅延メソッドを別の名前空間に移動し、
Linq
-ish を別の名前空間に保持して、少なくとも何らかのアイデアを提供しますか?IEnumerable
メソッドを実行するための as パラメーターを受け入れず、immediately
代わりに、より派生した型または具体的な型自体を使用してIEnumerable
、遅延メソッドだけを残しますか? これにより、実行されていない可能性のある式を実行するという負担が呼び出し元にかかりますか?Linq
外の世界ではIEnumerable
s をほとんど処理せず、ほとんどの基本的なコレクション クラスICollection
は少なくとも 1 つまで実装されているため、これは非常に可能です。
それとも何か?私は特に 3 番目のオプションが気に入っています。メソッド内でaまたは同様のLinq
ことを受け入れて実行する優れたプログラマーからの多くのコード (拡張メソッドに少し似ています!) を見てきました。彼らが副作用にどう対処するかはわかりません..IEnumerable
ToList()
編集:反対票と回答の後、プログラマーがLinqの仕組みを知らないわけではないことを明確にしたいと思います(私たちの習熟度はある程度のレベルにある可能性がありますが、それは別のことです)が、多くの関数が当時のLinqを考慮に入れました。現在、すぐに実行されるメソッドを Linq 拡張メソッドと一緒にチェーンすると危険です。だから私の質問は、Linq側から何を使用し、何を使用しないかを発信者に知らせるために、プログラマーが従う一般的なガイドラインがありますか? それは、使い方がわからない場合は助けられないというよりも、防御的にプログラミングすることです。(または少なくとも私は信じています)..