4

arrayの最初の3つの要素をLinQ Where拡張機能で削除しようとしています。ここでLinq VS Watchでローカルカウンタクロージャの結果が異なる場合

は一例です:

var array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
var count = 3; 
var deletedTest1 = 0; 
var test1 = array.Where(x => ++deletedTest1 > count).ToList(); 
Console.WriteLine($"{{{String.Join(", ", test1)}}}"); 
var deletedTest2 = 0; 
var test2 = array.Where(x => ++deletedTest2 > count).AsEnumerable(); 
Console.WriteLine($"{{{String.Join(", ", test2)}}}"); 
var deletedTest3 = 0; 
var test3 = array.Where(x => ++deletedTest3 > count); 
Console.WriteLine($"{{{String.Join(", ", test3)}}}"); 
var deletedTest4 = 0; 
var test4 = array.Where(x => ++deletedTest4 > count).ToArray(); 
Console.WriteLine($"{{{String.Join(", ", test4)}}}"); 

それが正常に動作し、それぞれの場合に、私はコンソール{ 4, 5, 6, 7, 8, 9 }結果を持っています。

しかしでのVisual Studio 2015の更新test2 3とtest3場合には、私は間違った結果があります。

enter image description here

を私は他のケースで.ToList().ToArray()と間違って使用する場合、すべてがOKである理由を誰もが説明できます?

このバグはありますか?

+4

を)'あなたが/リストにデータをマテリアライズされていますアレイ。他のものは実質的にデータを実行することを約束している 'IEnumerable'であり、' Console.WriteLine'に1回、デバッガでそれらを表示すると2回実行しています。バグはありません。 – DavidG

答えて

2

違いは、副作用を伴うラムダの遅延実行によるものです。 Whereによって生成されたIEnumerable<T>が列挙されるたびにラムダが評価され、副作用(すなわち、deletedTestXを増やす)が何度も繰り返されるため、ここでは非常に注意する必要があります。

プログラムを実行すると、4つのシーケンスのそれぞれが正確に1回列挙されます。ケース1と4の場合、列挙はToListToArrayの間で起こります。ケース2と3の場合は、string.Joinの内部で起こります。

デバッガで結果を開くと、ウォッチウィンドウのコントローラは結果を表示するために列挙を実行する必要があります。これはシーケンスの2番目の列挙です。そのため、既に適用されている最初の列挙の副作用が発生します。そのため、デバッグウィンドウで間違ったインデックスが表示されます。

あなたは二回、各結果を印刷して、あなたのプログラムの中でこの現象を再現することができます: `ToListメソッド()`と `てToArray(有

var array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
var count = 3; 
var deletedTest1 = 0; 
var test1 = array.Where(x => ++deletedTest1 > count).ToList(); 
Console.WriteLine("Test 1, deletedTest1={0}", deletedTest1); 
Console.WriteLine($"{{{String.Join(", ", test1)}}}"); 
Console.WriteLine("Test 1, deletedTest1={0}", deletedTest1); 
Console.WriteLine($"{{{String.Join(", ", test1)}}}"); 
var deletedTest2 = 0; 
var test2 = array.Where(x => ++deletedTest2 > count).AsEnumerable(); 
Console.WriteLine("Test 2, deletedTest2={0}", deletedTest2); 
Console.WriteLine($"{{{String.Join(", ", test2)}}}"); 
Console.WriteLine("Test 2, deletedTest2={0}", deletedTest2); 
Console.WriteLine($"{{{String.Join(", ", test2)}}}"); 
var deletedTest3 = 0; 
var test3 = array.Where(x => ++deletedTest3 > count); 
Console.WriteLine("Test 3, deletedTest3={0}", deletedTest3); 
Console.WriteLine($"{{{String.Join(", ", test3)}}}"); 
Console.WriteLine("Test 3, deletedTest3={0}", deletedTest3); 
Console.WriteLine($"{{{String.Join(", ", test3)}}}"); 
var deletedTest4 = 0; 
var test4 = array.Where(x => ++deletedTest4 > count).ToArray(); 
Console.WriteLine("Test 4, deletedTest4={0}", deletedTest4); 
Console.WriteLine($"{{{String.Join(", ", test4)}}}"); 
Console.WriteLine("Test 4, deletedTest4={0}", deletedTest4); 
Console.WriteLine($"{{{String.Join(", ", test4)}}}"); 

Demo.

関連する問題