2011-08-30 9 views
20

पहले से ही question on SO about "possible multiple enumerations" है, लेकिन यह प्रश्न अधिक विशिष्ट है।यहां तक ​​कि "IsNullOrEmpty" चेक भी "IENumerable की संभावित एकाधिक गणना" चेतावनियां

निम्न विधि है, जो इनपुट के रूप में एक IEnumerable<string> लेता है और उसके तत्वों में से प्रत्येक के खिलाफ दिए गए विधि कार्यान्वित करने पर विचार करें:

public static bool SomeMethod(IEnumerable<string> enumerable) 
{ 
    if (enumerable.IsNullOrEmpty()) 
    { 
     // throw exception. 
    } 
    else 
    { 
     return (enumerable.All(SomeBooleanMethod)); 
    } 
} 

उपरोक्त कोड में, IsNullOrEmpty सिर्फ एक विस्तार विधि है जो

चलाता है
return (!ReferenceEquals(enumerable, null) || enumerable.Any()); 

समस्या यह है कि ReSharper मुझे "आईनेमेरेबल के संभावित एकाधिक अंकन" के बारे में चेतावनी दे रहा है, और मुझे वास्तव में यह नहीं पता कि यह वास्तव में एक समस्या हो सकती है या नहीं।

मैं चेतावनी का अर्थ समझता हूं, लेकिन अगर आपको वास्तव में शून्यता या खालीता के मामले में अपवाद की जांच करने और अपवाद की आवश्यकता है तो आप वास्तव में क्या कर सकते हैं?

+0

खाली अनुक्रम पारित करने के लिए आप इस विधि को फेंकना क्यों चाहते हैं? "इस (खाली) अनुक्रम के प्रत्येक सदस्य को कुछ करने के अर्थशास्त्र" पूरी तरह से स्पष्ट हैं, है ना? साथ ही, क्या कोई विशेष कारण है कि आप 'Reference=quull()' का उपयोग केवल '== null' के बजाय क्यों करते हैं? – AakashM

+0

यह वास्तव में नहीं है, लेकिन अब कल्पना करें कि यह एक निर्माता था। यदि मैं किसी रिक्त अनुक्रम से ऑब्जेक्ट नहीं बना सकता, तो क्या मुझे एक सिवाय नहीं फेंकना चाहिए? – User

+1

निश्चित रूप से, यदि वास्तव में कुछ भी नहीं है तो आप कर सकते हैं; लेकिन * सामान्य रूप से * मैं कहूंगा कि खाली अनुक्रमों को किसी भी खाली रिक्त दृश्य के रूप में उतना ही अच्छा माना जाना चाहिए। उदाहरण के लिए, रिक्त अनुक्रम से निर्माण करने के लिए 'सूची <>' पूरी तरह से खुश है। बेशक मैं केवल सामान्यताओं में बात कर रहा हूं; आप अपनी स्थिति के * विवरण * जानते हैं। – AakashM

उत्तर

30

इसका मतलब है कि आप (आंशिक रूप से) एक से अधिक बार IENumerable पर पुनरावृत्त कर रहे हैं: पहले Any() पर कॉल करने के लिए (जिसे कम से कम एक पुनरावृत्ति शुरू करने की आवश्यकता है यह देखने के लिए कि कोई संख्या किसी तत्व को लौटाती है), और दूसरी बार All (जो शुरुआत से ही पुनरावृत्त होता है)।

कारण रेसर्पर आपको इस बारे में चेतावनी देता है कि एक गणित पर गणना करने से साइड इफेक्ट्स हो सकते हैं, और अनजाने में दो बार पुनरावृत्ति करने से दुष्प्रभाव दो बार ट्रिगर हो सकते हैं, जो वांछनीय हो सकता है या नहीं।

+0

क्या आप साइड इफेक्ट्स की व्याख्या कर सकते हैं या किसी भी उदाहरण से प्रसन्न होंगे। –

+12

आपका गणनीय, उदाहरण के लिए, नेटवर्क स्ट्रीम से बाइट्स पढ़ सकता है (जो साइड इफेक्ट का गठन करेगा)। यदि आप एक बार गिनती करते हैं, तो सब ठीक है, और स्ट्रीम एक बार में समाप्त होने के लिए पढ़ी जाती है। यदि, हालांकि, आप पहले पुनरावृत्ति को रोकते हैं और फिर पुन: प्रयास करते हैं, भले ही अंतर्निहित नेटवर्क स्ट्रीम पीछे की ओर नहीं जा सके, आपको सबसे अधिक संभावना अवांछित व्यवहार मिलेगा। – tdammers

+0

उदाहरण के लिए धन्यवाद –

8

@tdammers की पहचान के रूप में, "एकाधिक गणना" को संदर्भित किया गया है जो Any और All द्वारा आवश्यक दो गणनाएं हैं। चूंकि आप एक खाली अनुक्रम को अस्वीकार करना चाहते हैं, सबसे अच्छा मैं इसके साथ आ सकता हूं:

public static bool SomeMethod(IEnumerable<string> enumerable) 
{ 
    if (enumerable == null) 
     throw new ArgumentNullException(); 

    // Manually perform an All, keeping track of if there are any elements 
    bool anyElements = false; 

    bool result = true; 

    foreach (string item in enumerable) 
    { 
     anyElements = true; 
     result = result && SomeBooleanMethod(item); 

     // Can short-circuit here 
     if (!result) 
      break; 
    } 

    if (!anyElements) 
     throw new ArgumentException(); // Empty sequence is invalid argument 

    return result; 
} 
+1

प्रयास के लिए उपवास। –

संबंधित मुद्दे