यह उन लोगों के लिए एक प्रसिद्ध नुकसान है जो 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
।
इस तरह से लागू करने से Microsoft को क्या लाभ होने की उम्मीद थी?
कार्यान्वयन केवल एक आंतरिक सरणी के परिणाम को कैश क्यों नहीं करेगा? जो कुछ भी हो रहा है उसका एक विशिष्ट हिस्सा निष्पादन को स्थगित किया जा सकता है, लेकिन इसे अभी भी इस व्यवहार के बिना लागू किया जा सकता है।
एक बार LINQ द्वारा लौटाए गए संग्रह के किसी दिए गए सदस्य का मूल्यांकन किया गया है, आंतरिक संदर्भ / कॉपी नहीं रखने से क्या लाभ मिलता है, लेकिन एक ही परिणाम को एक डिफ़ॉल्ट व्यवहार के रूप में पुनर्गणना करते हुए?
उन स्थितियों में जहां एक संग्रह के एक ही सदस्य के लिए तर्क में एक विशेष आवश्यकता होती है, बार-बार पुनर्गणना होती है, ऐसा लगता है कि एक वैकल्पिक पैरामीटर के माध्यम से निर्दिष्ट किया जा सकता है और यह कि डिफ़ॉल्ट व्यवहार अन्यथा कर सकता है। इसके अलावा, गति लाभ जो आस्थगित निष्पादन द्वारा प्राप्त किया जाता है, अंततः उसी परिणाम को लगातार पुनर्गठित करने में लगने वाले समय के विरुद्ध वापस काट दिया जाता है। अंत में यह उन लोगों के लिए भ्रामक ब्लॉक है जो LINQ के लिए नए हैं, और यह अंततः किसी के कार्यक्रम में सूक्ष्म बग पैदा कर सकता है।
इसका क्या फ़ायदा है, और Microsoft ने ऐसा क्यों किया यह बहुत ही जानबूझकर लिया गया निर्णय है?
return listOfNames.Select(x => new Record(Guid.NewGuid(), x)).ToList();
यह आपको आपकी "कैश्ड कॉपी" देता है। समस्या सुलझ गयी।