これは、LINQを使用して足を濡らしている人々にとって既知の落とし穴です。
public class Program
{
public static void Main()
{
IEnumerable<Record> originalCollection = GenerateRecords(new[] {"Jesse"});
var newCollection = new List<Record>(originalCollection);
Console.WriteLine(ContainTheSameSingleObject(originalCollection, newCollection));
}
private static IEnumerable<Record> GenerateRecords(string[] listOfNames)
{
return listOfNames.Select(x => new Record(Guid.NewGuid(), x));
}
private static bool ContainTheSameSingleObject(IEnumerable<Record>
originalCollection, List<Record> newCollection)
{
return originalCollection.Count() == 1 && newCollection.Count() == 1 &&
originalCollection.Single().Id == newCollection.Single().Id;
}
private class Record
{
public Guid Id { get; }
public string SomeValue { get; }
public Record(Guid id, string someValue)
{
Id = id;
SomeValue = someValue;
}
}
}
これは、「False」を出力します。元のコレクションを作成するために指定された名前ごとに、選択関数が再評価され続け、結果のRecord
オブジェクトが新たに作成されるためです。これを修正するにToList
は、の最後にへの簡単な呼び出しを追加できますGenerateRecords
。
このように実装することで、マイクロソフトはどのような利点を得たいと考えましたか?
なぜ実装は結果を内部配列に単純にキャッシュしないのですか?何が起こっているかの特定の部分は、実行の遅延である場合がありますが、この動作がなくても実装できます。
LINQによって返されたコレクションの特定のメンバーが評価されると、内部参照/コピーを保持せずに、デフォルトの動作として同じ結果を再計算することによってどのような利点が提供されますか?
繰り返し再計算されるコレクションの同じメンバーのロジックに特定のニーズがある状況では、オプションのパラメーターを介して指定でき、デフォルトの動作は別の方法で実行できるようです。さらに、実行の遅延によって得られる速度の利点は、同じ結果を継続的に再計算するのにかかる時間によって最終的に削減されます。最後に、これはLINQを初めて使用する人にとっては混乱を招くブロックであり、最終的には誰のプログラムでも微妙なバグにつながる可能性があります。
これにはどのような利点があり、Microsoftはなぜこの一見非常に慎重な決定を下したのですか?
return listOfNames.Select(x => new Record(Guid.NewGuid(), x)).ToList();
これにより、「キャッシュされたコピー」が得られます。問題が解決しました。