นี่เป็นข้อผิดพลาดที่ทราบกันดีสำหรับผู้ที่เปียกปอนโดยใช้ 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;
}
}
}
สิ่งนี้จะพิมพ์ "เท็จ" เนื่องจากสำหรับแต่ละชื่อที่ให้มาเพื่อสร้างคอลเลกชันดั้งเดิมฟังก์ชันที่เลือกจะได้รับการประเมินค่าใหม่และRecord
วัตถุผลลัพธ์จะถูกสร้างขึ้นใหม่ เพื่อแก้ไขปัญหานี้เรียกง่ายๆที่จะอาจจะเพิ่มในตอนท้ายของToList
GenerateRecords
ไมโครซอฟท์หวังว่าจะได้ประโยชน์อะไรจากการใช้วิธีนี้?
เหตุใดการใช้งานจึงไม่เพียง แต่แคชผลลัพธ์ของอาร์เรย์ภายใน ส่วนหนึ่งที่เฉพาะเจาะจงของสิ่งที่เกิดขึ้นอาจถูกเลื่อนการดำเนินการ แต่ยังสามารถใช้งานได้หากไม่มีพฤติกรรมนี้
เมื่อสมาชิกที่ได้รับคอลเลกชันที่ส่งคืนโดย LINQ ได้รับการประเมินประโยชน์อะไรที่มีให้โดยการไม่เก็บการอ้างอิง / การคัดลอกภายใน แต่จะทำการคำนวณผลลัพธ์เดียวกันซ้ำอีกครั้งซึ่งเป็นพฤติกรรมเริ่มต้น
ในสถานการณ์ที่มีความต้องการเฉพาะในตรรกะสำหรับสมาชิกเดียวกันของคอลเลกชันที่คำนวณซ้ำแล้วซ้ำอีกดูเหมือนว่าจะสามารถระบุได้ผ่านพารามิเตอร์ทางเลือกและพฤติกรรมเริ่มต้นสามารถทำได้เป็นอย่างอื่น นอกจากนี้ความได้เปรียบด้านความเร็วที่ได้รับจากการดำเนินการแบบเลื่อนเวลาถูกลดทอนลงในที่สุดตามเวลาที่ใช้ในการคำนวณผลลัพธ์เดียวกันอย่างต่อเนื่อง ในที่สุดนี่คือบล็อกที่สับสนสำหรับผู้ที่ยังใหม่กับ LINQ และอาจนำไปสู่ข้อบกพร่องที่ลึกซึ้งในที่สุดโปรแกรมของทุกคน
มีข้อได้เปรียบอะไรบ้างในเรื่องนี้และทำไม Microsoft ถึงตัดสินใจอย่างรอบคอบ
return listOfNames.Select(x => new Record(Guid.NewGuid(), x)).ToList();
ที่ให้ "สำเนาแคช" ของคุณ แก้ไขปัญหา.