Ini adalah perangkap yang dikenal bagi orang-orang yang basah menggunakan 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;
}
}
}
Ini akan mencetak "Salah", karena untuk setiap nama yang disediakan untuk membuat koleksi asli, fungsi pilih terus dievaluasi ulang, dan Record
objek yang dihasilkan dibuat lagi. Untuk memperbaiki ini, panggilan sederhana ke ToList
dapat ditambahkan di akhir GenerateRecords
.
Apa keuntungan yang Microsoft harapkan untuk dapatkan dengan mengimplementasikannya dengan cara ini?
Mengapa implementasi tidak akan hanya menyimpan hasil cache array internal? Satu bagian spesifik dari apa yang terjadi mungkin eksekusi yang ditangguhkan, tetapi itu masih bisa dilaksanakan tanpa perilaku ini.
Setelah anggota tertentu dari koleksi yang dikembalikan oleh LINQ telah dievaluasi, keuntungan apa yang diberikan dengan tidak menyimpan referensi / salinan internal, tetapi sebaliknya menghitung ulang hasil yang sama, sebagai perilaku default?
Dalam situasi di mana ada kebutuhan khusus dalam logika untuk anggota yang sama dari koleksi yang dihitung ulang berulang kali, sepertinya itu dapat ditentukan melalui parameter opsional dan bahwa perilaku default dapat melakukan sebaliknya. Selain itu, keuntungan kecepatan yang diperoleh dengan eksekusi yang ditangguhkan pada akhirnya mengurangi waktu yang diperlukan untuk terus menghitung ulang hasil yang sama. Akhirnya ini adalah blok yang membingungkan bagi mereka yang baru mengenal LINQ, dan itu dapat menyebabkan bug halus pada akhirnya program siapa pun.
Apa keuntungannya untuk ini, dan mengapa Microsoft membuat keputusan yang tampaknya sangat disengaja ini?
return listOfNames.Select(x => new Record(Guid.NewGuid(), x)).ToList();
Itu memberi Anda "salinan cache." Masalah terpecahkan.