संपादित करें (संशोधित): यह उत्तर दो बार निष्पादित क्वेरी के मुद्दे को संबोधित करता है, जो मुझे विश्वास है कि यह मुख्य मुद्दा है। नीचे देखें:
बनाना Any()
स्मार्ट कुछ ऐसा है जो केवल लिंकक कार्यान्वयन कर सकता है, आईएमओ ... या यह प्रतिबिंब का उपयोग करके कुछ गंदा साहसिक होगा।
एक वर्ग का प्रयोग के रूप में नीचे दिखाया गया है, आप मूल गणनीय के उत्पादन में कैश कर सकते, और यह दो बार प्रगणित किया:
public class CachedEnumerable<T>
{
public CachedEnumerable(IEnumerable<T> enumerable)
{
_source = enumerable.GetEnumerator();
}
public IEnumerable<T> Enumerate()
{
int itemIndex = 0;
while (true)
{
if (itemIndex < _cache.Count)
{
yield return _cache[itemIndex];
itemIndex++;
continue;
}
if (!_source.MoveNext())
yield break;
var current = _source.Current;
_cache.Add(current);
yield return current;
itemIndex++;
}
}
private List<T> _cache = new List<T>();
private IEnumerator<T> _source;
}
इस तरह आप LINQ के आलसी पहलू रखने के लिए, कोड पठनीय रखने के लिए और सामान्य। यह धीमा हो जाएगा कि सीधे IEnumerator<>
का उपयोग करें। इस वर्ग को विस्तारित करने और अनुकूलित करने के कई अवसर हैं, जैसे पुरानी वस्तुओं को हटाने, कोरआउट आदि से छुटकारा पाने के लिए नीति। लेकिन यह मुझे लगता है कि इस सवाल के बिंदु से परे है।
ओह, और कक्षा अब थ्रेड सुरक्षित नहीं है। यह नहीं पूछा गया था, लेकिन मैं कल्पना कर रहा हूं कि लोग कोशिश कर रहे हैं। मुझे लगता है कि यह आसानी से जोड़ा जा सकता है, अगर स्रोत संख्यात्मक कोई धागा संबंध नहीं है ..
यह इष्टतम क्यों होगा?
चलो दो possibilites पर विचार करें: गणना तत्वों को दूषित कर सकता है या नहीं।
- यदि इसमें तत्व हैं, तो यह दृष्टिकोण इष्टतम है क्योंकि क्वेरी केवल एक बार चलती है।
- यदि इसमें कोई तत्व नहीं है, तो आप ऑर्डरबी को खत्म करने और अपने प्रश्नों का चयन करने के लिए परीक्षा देंगे, क्योंकि वे कोई मूल्य नहीं जोड़ते हैं। लेकिन ..
Where()
खंड के बाद शून्य आइटम हैं, तो सॉर्ट करने के लिए शून्य आइटम हैं, जो शून्य समय (अच्छी तरह से, लगभग) खर्च होंगे। Select()
खंड के लिए भी यही है।
क्या होगा यदि यह अभी तक पर्याप्त तेज़ नहीं है? उस स्थिति में मेरी रणनीति लिंक को बाईपास करना होगा। अब, मुझे वास्तव में linq पसंद है, लेकिन यह लालित्य कीमत पर आता है। इसलिए लिंक का उपयोग करने के हर 100 गुना के लिए, आम तौर पर एक या दो कंप्यूटेशंस होंगे जो वास्तव में तेजी से निष्पादित करने के लिए महत्वपूर्ण हैं, जो मैं लूप और सूचियों के लिए अच्छे पुराने के साथ लिखता हूं। एक तकनीक मास्टरिंग का हिस्सा यह पहचान रहा है कि यह उचित नहीं है। लिंक उस नियम के लिए अपवाद नहीं है।
स्रोत
2012-07-06 05:57:39
यह ठीक काम करता है, लेकिन केवल इसलिए कि उसके पास 'if' और 'foreach' के बीच कोई कोड नहीं था। – Gabe
@Gabe: मुझे समझ में नहीं आता है। अगर और foreach के बीच कोई कोड नहीं है। हमें अन्यथा क्यों ग्रहण करना चाहिए? – Ani
मैं स्मृति से पुनः टाइप कर रहा था, कोड वास्तव में 'if (condition && query.Any()) {/ * .. */foreach {..}/* .. * /} 'की तरह अधिक है। हां, मैं foreach को अनलॉक कर सकता हूं और इसे अधिक कुशलतापूर्वक (पठनीयता की कीमत पर) कर सकता हूं, लेकिन पहले आइटम को दो बार प्राप्त करना बुरा नहीं है (और यह बाध्य है)। हालांकि पूरे अनुक्रम ... मैं और जटिल परिस्थितियों के बारे में भी सोच रहा हूं जहां प्रश्न अलग-अलग लोगों द्वारा लिखे गए हैं या लिखे गए हैं, जहां केवल मध्यवर्ती मूल्य का उपयोग करना मुश्किल हो सकता है। – Fowl