JonSkeetのReimplemntingLinqtoObjectsシリーズを実行していました。whereの記事の実装で、次のスニペットを見つけましたが、元のメソッドを2つに分割することで得られる利点がわかりません。
元の方法:
// Naive validation - broken!
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (predicate == null)
{
throw new ArgumentNullException("predicate");
}
foreach (TSource item in source)
{
if (predicate(item))
{
yield return item;
}
}
}
リファクタリングされた方法:
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (predicate == null)
{
throw new ArgumentNullException("predicate");
}
return WhereImpl(source, predicate);
}
private static IEnumerable<TSource> WhereImpl<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
foreach (TSource item in source)
{
if (predicate(item))
{
yield return item;
}
}
}
ジョンは言います-それは熱心な検証のためであり、それから残りの部分のために延期します。でも、わかりません。
誰かがそれをもう少し詳しく説明してもらえますか、これら2つの機能の違いは何ですか、そしてなぜ検証が一方で実行され、もう一方では熱心に実行されないのですか?
結論/解決策:
どの関数がイテレータージェネレーターであると判断されるかについての理解が不足していたため、混乱しました。IEnumerable
<T>
のようなメソッドのシグネチャに基づいていると思い ました。しかし、答えに基づいて、今私はそれを理解しました、それがyield ステートメントを使用する場合、メソッドはイテレーター-ジェネレーターです。