2010-01-27 11 views
14

मैं थोड़ा उत्सुक हूं क्योंकि इसे FirstOrDefault की बात आने पर "सर्वोत्तम अभ्यास" माना जाता है।फर्स्टऑर्डडिफॉल्ट() लम्बा के साथ फर्स्टऑर्डडिफॉल्ट() के साथ LINQ बनाम?

मैंने पहले से ही यह प्रश्न देखा है, जो मेरे पास मौजूद प्रश्न के समान है, लेकिन मेरे प्रश्न का उत्तर देने के लिए पर्याप्त नहीं है।

इनमें से कौन सा "बेहतर कोड" है? और क्यों?

var foos = GetMyEnumerableFoos(); 

var foo1 = (from f in foos 
    where f.Bar == "spider monkey" 
    select f).FirstOrDefault(); 

/* OR */ 

var foo2 = foos.FirstOrDefault(f => f.Bar == "spider monkey"); 

मैं, बाद की ओर जाते हैं के रूप में IMO, यह क्लीनर कोड के लिए बनाता है। लेकिन मैं उत्सुक हूं कि तकनीक पर "क्या चल रहा है" की "गड़बड़ी" है या नहीं, दूसरी तरफ अधिक कुशल है। यदि आप विभिन्न प्रकार के आईनेमरेबल्स का उपयोग कर रहे हैं तो क्या यह बदलता है? डेटाटेबल्स या स्ट्रिंग एरे या LINQ ऑब्जेक्ट्स की तरह?

========= संपादित ==========

मान लिया जाये कि जॉन स्कीट की पोस्ट सही है, मैं परावर्तक में देख चला गया क्या कहाँ और FirstOrDefault की तरह लग रही देखने के लिए, और

foos.Where के मामले में (च => f.Bar == "मकड़ी बंदर") FirstOrDefault()

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
{ 
    if (source == null) 
    { 
     throw Error.ArgumentNull("source"); 
    } 
    if (predicate == null) 
    { 
     throw Error.ArgumentNull("predicate"); 
    } 
    if (source is Iterator<TSource>) 
    { 
     return ((Iterator<TSource>) source).Where(predicate); 
    } 
    if (source is TSource[]) 
    { 
     return new WhereArrayIterator<TSource>((TSource[]) source, predicate); 
    } 
    if (source is List<TSource>) 
    { 
     return new WhereListIterator<TSource>((List<TSource>) source, predicate); 
    } 
    return new WhereEnumerableIterator<TSource>(source, predicate); 
} 

जो में फ़ीड होगा: यहाँ क्या मैं के साथ आया है।:

public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source) 
{ 
    if (source == null) 
    { 
     throw Error.ArgumentNull("source"); 
    } 
    IList<TSource> list = source as IList<TSource>; 
    if (list != null) 
    { 
     if (list.Count > 0) 
     { 
      return list[0]; 
     } 
    } 
    else 
    { 
     using (IEnumerator<TSource> enumerator = source.GetEnumerator()) 
     { 
      if (enumerator.MoveNext()) 
      { 
       return enumerator.Current; 
      } 
     } 
    } 
    return default(TSource); 
} 

foos.FirstOrDefault (f => f.Bar == "मकड़ी बंदर") के मामले में; कि कम से

public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
{ 
    if (source == null) 
    { 
     throw Error.ArgumentNull("source"); 
    } 
    if (predicate == null) 
    { 
     throw Error.ArgumentNull("predicate"); 
    } 
    foreach (TSource local in source) 
    { 
     if (predicate(local)) 
     { 
      return local; 
     } 
    } 
    return default(TSource); 
} 

देख रहे हैं अभी भी मुझे थोड़ा उलझन में छोड़ देता है, वहाँ क्षमता निश्चित वस्तु प्रकार के लिए उचित इटरेटर का उपयोग करके जोड़ा जाएगा? या क्या यह सब छोड़ने और परीक्षण के माध्यम से लूपिंग शुरू करना अधिक कुशल है? मेरा आंत फिर मुझे बताता है कि यह बाद वाला है।

उत्तर

17

ठीक है, "का चयन करें" भाग संकलक द्वारा वैसे भी निकाल दिया जाएगा, ताकि आप वास्तव में तुलना कर रहे हैं:

foo.Where(f => f.Bar == "spider monkey") 
    .FirstOrDefault() 

बनाम

foo.FirstOrDefault(f => f.Bar == "spider monkey") 

मुझे शक है कि यह किसी भी महत्वपूर्ण कर देगा वैसे भी LINQ से ऑब्जेक्ट्स के भीतर दक्षता में अंतर। मैं व्यक्तिगत रूप से बाद के संस्करण का व्यक्तिगत रूप से उपयोग करता हूं ... जब तक कि मैं अन्यत्र क्वेरी के फ़िल्टरिंग हिस्से का पुन: उपयोग नहीं करना चाहता था।

+0

यह दिलचस्प है। आपके द्वारा उल्लेखित तीन तरीकों में क्या हो रहा है यह देखने के लिए कि आप पोस्ट करने के बाद पोस्ट कर रहे हैं, मैंने थोड़ी अधिक खुदाई की। मैंने उपरोक्त मेरे निष्कर्ष पोस्ट किए हैं ... यह निश्चित रूप से मेरे प्रश्न का उत्तर देने में मदद करता है। –

+0

मैंने चेक नहीं किया है, लेकिन मुझे लगता है कि '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ', जहां' FirstOrDefault (predicate) 'कॉल स्पष्ट रूप से कॉल करता है। तो 'कहां' संस्करण में 'झूठी' प्रति एक अतिरिक्त कॉल है (और अंतिम 'सत्य', यदि मौजूद है) 'predicate'। –

4

मैं बाद वाले को पसंद करता हूं क्योंकि यह अधिक संक्षिप्त है।

यह दक्षता की शर्तें मुझे संदेह है कि आप 2 के बीच एक बड़ा अंतर पा सकते हैं। वे व्यावहारिक रूप से व्यवहार में समान हैं, भले ही वे अभ्यास में थोड़ा अलग काम करते हैं।

सबसे बड़ा अंतर यह है कि पहला व्यक्ति नया IEnumerable<T> उदाहरण बनाता है जो तब पहले तत्व के लिए चलाया जाता है। बाद के मामले में, मौजूदा IEnumerable<T> उदाहरण भविष्यवाणी से मेल खाने वाले पहले मान के लिए चलाया गया है। फिर, ध्यान देने योग्य बहुत संभावना नहीं है।

-1

दूसरा संस्करण अधिक कुशल होगा।

पहले संस्करण

var foo1 = (from f in foos 
    where f.Bar == "spider monkey" 
    select f).FirstOrDefault(); 

विल हमेशा सभी वस्तुओं के माध्यम से लूप, मिलान आइटम का एक नया संग्रह बनाने।

दूसरे संस्करण

var foo2 = foos.FirstOrDefault(f => f.Bar == "spider monkey"); 

केवल आइटम के माध्यम से लूप जब तक कोई मिलान पाया है और फिर होगा लौट आए।

+3

असल में, यदि आप अपने LINQ में ब्रेक पॉइंट डालते हैं तो आप इसे देखेंगे ... लेकिन यह केवल एक बार LINQ कथन निष्पादित करेगा। आपके पास LINQ कथन भी हो सकते हैं जो LINQ कथन विज्ञापन नोडम द्वारा बनाए गए आईनेमरेबल्स तक पहुंच सकते हैं और यदि आप FirstOrDefault को कॉल करते हैं तो यह अभी भी केवल एक बार उनके माध्यम से जाएगा। कोई चिंता नहीं, हालांकि, मैं वही बात सोचता था। ;) –

+1

कथन "मिलान वस्तुओं के नए संग्रह को बनाने, सभी वस्तुओं के माध्यम से हमेशा लूप करेगा" दो मायने रखता है। सबसे पहले यह 'फूओस' में सभी वस्तुओं के माध्यम से केवल तभी होगा जब कोई 'मकड़ी बंदर' न हो, अन्यथा यह पहले "मकड़ी बंदर" को हिट करने पर रोक देगा। दूसरा, यह मिलान करने वाले आइटमों का संग्रह नहीं बनाएगा, यह _first_ एक देता है। –

+2

मुझे लगता है कि @phdesign कोष्ठक की उपस्थिति के कारण भ्रमित कर दिया गया था - उसने माना कि अंदर सबकुछ पहले निष्पादित हो जाता है (क्योंकि यह आमतौर पर ब्रांड्स का होता है)। हालांकि, यह नियम इस मामले में लागू नहीं होता है, वे केवल समूह निर्माण के रूप में ही हैं। –

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