ढूँढें () बनाम कहाँ ()। FirstOrDefault ()


161

मैं अक्सर लोगों Where.FirstOrDefault()को खोज करने और पहले तत्व को हथियाने के लिए उपयोग करता हूं। सिर्फ उपयोग क्यों नहीं Find()? क्या दूसरे के लिए एक फायदा है? मैं एक अंतर नहीं बता सकता।

namespace LinqFindVsWhere
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> list = new List<string>();
            list.AddRange(new string[]
            {
                "item1",
                "item2",
                "item3",
                "item4"
            });

            string item2 = list.Find(x => x == "item2");
            Console.WriteLine(item2 == null ? "not found" : "found");
            string item3 = list.Where(x => x == "item3").FirstOrDefault();
            Console.WriteLine(item3 == null ? "not found" : "found");
            Console.ReadKey();
        }
    }
}

45
FWIW, list.FirstOrDefault(x => x == "item3");दोनों का उपयोग करने की तुलना में अधिक संक्षिप्त है .Whereऔर .FirstOrDefault
Kirk Woll

@ किर्क, मुझे लगता है कि मेरा अगला सवाल यह होगा कि उन्होंने सभी को क्यों जोड़ा। यह एक अच्छी टिप है। केवल एक चीज जो मैं सोच सकता हूं वह यह है कि FirstOrDefault null के अलावा एक अलग डिफ़ॉल्ट मान लौटा सकता है। अन्यथा यह सिर्फ एक व्यर्थ जोड़ की तरह लगता है।
KingOfHypocrites

8
FindLINQ को दर्शाता है। (यह .NET 2.0 में उपलब्ध था और आप लैम्ब्डा का उपयोग नहीं कर सकते। आपको सामान्य तरीकों या अनाम विधियों का उपयोग करने के लिए मजबूर किया गया था)
Kirk Woll

जवाबों:


205

Findविधि कहाँ पर है IEnumerable<T>? (आलंकारिक प्रश्न।)

Whereऔर FirstOrDefaultतरीकों दृश्यों के कई प्रकार सहित, के खिलाफ लागू होते हैं List<T>, T[], Collection<T>, आदि कोई भी क्रम कि औजार IEnumerable<T>इन पद्धतियों का उपयोग कर सकते हैं। Findके लिए ही उपलब्ध है List<T>। आम तौर पर लागू होने वाले तरीके, फिर अधिक पुन: प्रयोज्य होते हैं और अधिक प्रभाव डालते हैं।

मुझे लगता है कि मेरा अगला सवाल यह होगा कि उन्होंने सभी को क्यों जोड़ा। यह एक अच्छी टिप है। केवल एक चीज जो मैं सोच सकता हूं वह यह है कि FirstOrDefault null के अलावा एक अलग डिफ़ॉल्ट मान लौटा सकता है। अन्यथा यह सिर्फ एक व्यर्थ जोड़ की तरह लगता है

Findपर List<T>पहले का है अन्य तरीकों। List<T>.NET 2.0 में जेनरिक के साथ जोड़ा गया था, और Findउस वर्ग के लिए एपीआई का हिस्सा था। Whereऔर Linq FirstOrDefaultके IEnumerable<T>साथ विस्तार विधियों के रूप में जोड़े गए , जो बाद में .NET संस्करण है। मैं निश्चित रूप से यह नहीं कह सकता कि अगर लिनक 2.0 रिलीज के साथ मौजूद था जो Findकभी नहीं जोड़ा जाता था, लेकिन यह यकीनन कई अन्य विशेषताओं के लिए मामला है जो पहले .NET संस्करणों में आए थे जिन्हें बाद के संस्करणों द्वारा अप्रचलित या निरर्थक बना दिया गया था।


85
बस पूरक करने के लिए: जहां और पहले या FirstOrDefault को कॉल करने की कोई आवश्यकता नहीं है: या तो First या FirstOrDefault आपको एक खोज विधेय को निर्दिष्ट करने की अनुमति देता है, जहां अनावश्यक कॉल
Robson Rocha

4
लेकिन Where(condition).FirstOrDefault()कम से कम के रूप में अच्छी तरह से और कभी-कभी FirstOrDefault(condition)अकेले से बेहतर अनुकूलन करता है । हम हमेशा Where()उपलब्ध प्रदर्शन में सुधार लाने के लिए उपयोग करते हैं।
Suncat2000

7
@ Suncat2000 कृपया एक उदाहरण प्रदान करें
Konstantin Salavatov

2
@ Suncat2000 आप अपनी अभिव्यंजक शक्ति के Linq becasue का उपयोग कर रहे हैं और घोषणात्मक कोड लिखना चाहते हैं। आपको ऐसे सूक्ष्म सुधारों से चिंतित नहीं होना चाहिए, जो भविष्य के कार्यान्वयन में भी बदल सकते हैं। इसके अलावा, बहुत जल्दी अनुकूलन न करें
Piotr Falkowski

50

मुझे अभी पता चला है, 80K वस्तुओं की सूची पर कुछ परीक्षण कर रहा है और पाया कि Find()एक के Whereसाथ प्रयोग करने की तुलना में 1000% तक तेज हो सकता है FirstOrDefault()। मुझे नहीं पता था कि एक टाइमर का परीक्षण करने से पहले और बाद में सभी। कभी-कभी यह एक ही समय था, अन्यथा यह तेज था।


6
क्या आपने इसे कहाँ और FirstOrDefault के साथ आज़माया है? यदि आपने शायद इसे केवल FirstOrDefault के साथ आज़माया है और देखें कि क्या Find () अभी भी बेहतर है।
MVCKarl 11

5
ऐसा लगता है कि आपने परिणाम को वास्तव में क्वेरी करने के लिए .ToList()या उसके साथ परिणाम नहीं दिया .ToArray()
एंड्रयू मॉर्टन

4
इसका कारण यह है कि Findप्राथमिक कुंजियों (इसलिए अनुक्रमित) का उपयोग करता है, जबकि Whereएक सादा एसक्यूएल क्वेरी है
10:48

4
EF6 के रूप में, ढूँढें और FirstOrDefault दोनों समान SQL कथन उत्पन्न करते हैं। आप एक कंसोल ऐप में SQL को संदर्भ में देख सकते हैं। Database.Log = Console.Write; बैठा उदाहरण स्ट्रिंग्स की एक सूची के खिलाफ "मेमोरी" का उपयोग कर रहा है, प्राथमिक कुंजी के साथ एक डीबी के खिलाफ नहीं जा रहा है। शायद खोजें खंड का कथन अनुवाद - जो लंबोदर अभिव्यक्ति पार्स करने की आवश्यकता को छोड़ता है, इस मामले में प्रदर्शन में सुधार का कारण है। एक डेटाबेस के खिलाफ मुझे संदेह है कि आपको आरएल स्थितियों में अंतर दिखाई देगा ... मुझे आश्चर्य है कि अगर इसे दूसरे के बजाय पहली बार खोजें का उपयोग करके परीक्षण किया गया ...
C.List

2
खैर, इस प्रदर्शन में सुधार इसलिए है क्योंकि डीबी मारने से पहले ऑब्जेक्ट के लिए कैश में चेक () चेक करें, जबकि () हमेशा ऑब्जेक्ट प्राप्त करने के लिए डीबी पर जाएं
गौरव

35

यदि डेटा का स्रोत एंटिटी फ्रेमवर्क है, तो एक बहुत ही महत्वपूर्ण अंतर है: Find'जोड़े गए' राज्य में ऐसी इकाइयाँ मिलेंगी जो अभी तक कायम नहीं हैं, लेकिन Whereनहीं होंगी। यह डिजाइन द्वारा है।



1

एंथोनी जवाब के अलावा Where()सभी रिकॉर्ड के माध्यम से यात्रा करते हैं और फिर परिणाम (ओं) को वापस करते हैं, जबकि Find()सभी रिकॉर्डों के माध्यम से ट्रैवस करने की आवश्यकता नहीं होती है यदि दिए गए विधेय के साथ मेल खाते हैं।

इसलिए कहते हैं कि आपके पास टेस्ट क्लास की सूची idऔर nameगुण हैं।

 List<Test> tests = new List<Test>();
 tests.Add(new Test() { Id = 1, Name = "name1" });
 tests.Add(new Test() { Id = 2, Name = "name2" });
 tests.Add(new Test() { Id = 3, Name = "name3" });
 tests.Add(new Test() { Id = 4, Name = "name2" }); 
 var r = tests.Find(p => p.Name == "name2");
 Console.WriteLine(r.Id);

का आउटपुट देगा 2, और केवल 2 विज़िट परिणाम देने के लिए आवश्यक खोजें, लेकिन यदि आप उपयोग Where().FirstOrDefault()करते हैं तो हम सभी रिकॉर्डों का दौरा करेंगे और फिर हमें परिणाम मिलेंगे।

इसलिए, जब आप जानते हैं कि आप केवल संग्रह में रिकॉर्ड से पहला परिणाम चाहते हैं Find()तब अधिक उपयुक्त होगाWhere().FirtorDefault();


4
लेकिन अगर आप कहां () का उपयोग करते हैं। FirstOrDefault () हम सभी रिकॉर्ड्स पर जाएंगे और फिर हमें परिणाम मिलेंगे। नहीं। FirstOrDefaultचेन को 'बबल-अप' करेंगे और हर चीज को एन्यूमरेट करना बंद कर देंगे। मैं बेहतर अभिव्यक्ति की कमी के लिए 'बबल-अप' शब्द का उपयोग करता हूं, क्योंकि वास्तव में प्रत्येक चयनकर्ता / विधेय को अगले पर पारित किया जाएगा, इसलिए श्रृंखला में अंतिम विधि वास्तव में पहले काम कर रही है।
सिल्वरमाइंड

1

वाह, मैं अभी Youtube पर MicrosofToolbox से EF ट्यूटोरियल देखता हूं। उन्होंने क्वेरी में Find () और FirstOrDefault (स्थिति) का उपयोग करने के बारे में कहा था और Find () उस ऑब्जेक्ट पर आपके द्वारा किए गए डेटा को खोजेगा (जोड़ें या संपादित करें या हटाएं - लेकिन अभी तक डेटाबेस में सहेजा नहीं गया है) इस बीच FirstOrDefault केवल पहले से ही सहेजे गए हैं के लिए देखो


-1

Find()IEnumerable एक के बराबर है FirstOrDefault()। आप के साथ दोनों .Where () श्रृंखला नहीं करना चाहिए .FirstOrDefault()क्योंकि .Where()पूरे सरणी के माध्यम से चला जाता है और फिर उस सूची के माध्यम से पुनरावृति पहला आइटम खोजने के लिए होगा। आप अपनी खोज FirstOrDefault()विधि में विधेय डालकर अविश्वसनीय समय बचाते हैं ।

इसके अलावा, मैं आपको .Find()विशिष्ट परिदृश्यों के प्रदर्शन () बनाम FirstOrDefault () के उपयोग से बेहतर प्रदर्शन के बारे में अधिक जानने के लिए इस प्रश्न से जुड़े प्रश्न को पढ़ने के लिए प्रोत्साहित करता हूं


यह आपके ऊपर दिए गए उत्तर का एक डुप्लिकेट है। इसके अलावा, सिल्वरमाइंड की टिप्पणी को उस उत्तर पर देखें।
carlin.scott
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.