उचित Linq जहां खंड


133

मैं अपने दिन-प्रतिदिन के जीवन में उचित मात्रा में लिंकन लिखता हूं, लेकिन ज्यादातर सरल कथन। मैंने देखा है कि जहां क्लॉज़ का उपयोग करते समय, उन्हें लिखने के कई तरीके हैं और प्रत्येक के पास वही परिणाम हैं जहां तक ​​मैं बता सकता हूं। उदाहरण के लिए;

from x in Collection
  where x.Age == 10
  where x.Name == "Fido"
  where x.Fat == true
  select x;

परिणाम के संबंध में यह कम से कम समतुल्य होने की अपील करता है:

from x in Collection
  where x.Age == 10 &&
        x.Name == "Fido" &&
        x.Fat == true
  select x;

तो क्या सिंटैक्स के अलावा वास्तव में कोई अंतर है? यदि हां, तो पसंदीदा शैली क्या है और क्यों?


203
आपके पास बूलियन Fatप्रॉपर्टी है? वह सादा मतलब है।
बाला आर

104
@ बाला आर: अरे, अगर आपका कुत्ता मोटा है, तो आपका कुत्ता मोटा है।
एआर

जवाबों:


76

दूसरा एक और अधिक कुशल होगा क्योंकि इसके पास संग्रह में प्रत्येक आइटम के खिलाफ मूल्यांकन करने के लिए एक विधेय है जहां पहले एक के रूप में, यह पहले सभी वस्तुओं के लिए पहली विधेय को लागू कर रहा है और परिणाम (जो इस बिंदु पर नीचे संकुचित है) दूसरे के लिए प्रयोग किया जाता है विधेय और इतने पर। परिणाम हर पास से कम हो जाते हैं लेकिन फिर भी इसमें कई पास शामिल होते हैं।

इसके अलावा जंजीर (पहली विधि) केवल तभी काम करेगी जब आप अपनी भविष्यवाणी कर रहे हों। ऐसा कुछ x.Age == 10 || x.Fat == trueआपके पहले तरीके के साथ काम नहीं करेगा।


1
चेन ओरिंग की स्थिति कुछ हद तक इस विस्तार का उपयोग कर संभव है: albahari.com/nutshell/predicatebuilder.aspx
jahu

142

संपादित करें: वस्तुओं के लिए LINQ यह व्यवहार नहीं करता है कि मैं कैसे इसकी अपेक्षा करूँगा। आप अच्छी तरह से इस बारे में लिखा है ब्लॉग पोस्ट में रुचि हो सकती है ...


वे कहे जाने वाले शब्दों में भिन्न हैं - पहला इसके समकक्ष है:

Collection.Where(x => x.Age == 10)
          .Where(x => x.Name == "Fido")
          .Where(x => x.Fat == true)

बाद वाले के बराबर है:

Collection.Where(x => x.Age == 10 && 
                      x.Name == "Fido" &&
                      x.Fat == true)

अब वास्तव में क्या अंतर पड़ता है Whereजिसे कहा जाने के कार्यान्वयन पर निर्भर करता है । यदि यह SQL- आधारित प्रदाता है, तो मुझे उम्मीद है कि दोनों एक ही SQL बनाने की समाप्ति करेंगे। यदि यह LINQ में ऑब्जेक्ट्स के लिए है, तो दूसरे में अप्रत्यक्ष स्तर कम होंगे (चार के बजाय इसमें केवल दो पुनरावृत्त होंगे)। क्या गति के मामले में अप्रत्यक्ष स्तर महत्वपूर्ण हैं या नहीं यह अलग बात है।

आमतौर पर मैं कई whereखंडों का उपयोग करूँगा यदि उन्हें लगता है कि वे काफी भिन्न स्थितियों का प्रतिनिधित्व कर रहे हैं (जैसे कि एक वस्तु के एक हिस्से के साथ क्या करना है, और एक पूरी तरह से अलग है) और एक whereखंड जब विभिन्न स्थितियों को निकटता से संबंधित (जैसे एक विशेष मूल्य) न्यूनतम से अधिक है और अधिकतम से कम है)। मूल रूप से यह किसी भी मामूली प्रदर्शन अंतर से पहले पठनीयता पर विचार करने के लायक है।


1
@JonSkeet शायद मैं गलत हूं, लेकिन Linq की त्वरित समीक्षा के बाद कहां कार्यान्वयन, मुझे इस पर यकीन नहीं है। नेस्टेड कहाँ एक स्थिर विधि 'CombinePredicates' द्वारा संयुक्त हैं। संयुक्त विधेय के साथ एकल पुनरावृत्तिकर्ता द्वारा केवल एक बार संग्रह को पुनरावृत्त किया जाता है। बेशक, फंक के संयोजन का एक प्रदर्शन प्रभाव है, लेकिन यह बहुत सीमित है। आप ठिक हो ?
साइबरमैक्स 11

@Cybermaxs: क्या , ठीक से निश्चित नहीं है ? मैंने कभी सुझाव नहीं दिया कि संग्रह को एक से अधिक बार प्रसारित किया जाएगा।
जॉन स्कीट

@JonSkeet हां जरूर लेकिन अंत में सभी विधेय संयुक्त हैं और केवल एक पुनरावृत्ति करने वाला अवांछित है। AtEnumerable.WhereSelectEnumerableIterator देखें।
साइबरमैक्स

आपके द्वारा लिंक किया गया पृष्ठ अभी नीचे है। अगर लेख अभी भी कहीं और है तो क्या आप लिंक को अपडेट कर सकते हैं? धन्यवाद।
असद सईदुद्दीन 16

2
@ असद: अपडेट किया गया। (मेरा ब्लॉग स्थानांतरित हो गया है।)
जॉन स्कीट

13

पहले एक को लागू किया जाएगा:

Collection.Where(x => x.Age == 10)
          .Where(x => x.Name == "Fido") // applied to the result of the previous
          .Where(x => x.Fat == true)    // applied to the result of the previous

बहुत सरल (और कहीं अधिक तेजी से अधिक तेज) के विपरीत :

// all in one fell swoop
Collection.Where(x => x.Age == 10 && x.Name == "Fido" && x.Fat == true)

6
"बहुत तेज"? हम यह भी नहीं जानते हैं कि कौन सा LINQ कार्यान्वयन अभी तक शामिल है, इसलिए किसी भी प्रदर्शन निहितार्थ को संलग्न करना कठिन है।
जॉन स्कीट

सामान्य मामले में उत्तरार्द्ध को केवल 1 लूप की आवश्यकता होती है। एक प्रदाता पहले उदाहरण को समतल करना चुन सकता है, लेकिन इसकी आवश्यकता नहीं है।
user7116

2
दरअसल ... लेकिन यदि आप बाद का दावा कर रहे हैं है अब तक तेजी से। ऐसा नहीं है कि यह हो जाएगा सब स्पष्ट में नहीं है काफी सब के बाद, प्रदर्शन अंतर का महत्व यह कैसे किया जा रहा है पर निर्भर करेगा - तेजी से सब पर।
जॉन स्कीट

1
@ जॉन: कोई असहमति नहीं। जैसा कि आप ध्यान दें कि वास्तविकता हो सकती है LINQ प्रदाता जाता है और अभिव्यक्ति के लिए उपयोगी अनुकूलन परिवर्तन करता है। लेकिन दूसरे को देखते हुए केवल एक लूप की आवश्यकता होती है और बूलियन शॉर्ट सर्किटिंग से लाभ होता है, यह देखना मुश्किल है कि इसे सामान्य शब्दों में "अधिक तेज़" क्यों नहीं कहा जाना चाहिए। यदि ओपी में केवल 5 तत्व हैं तो मेरी बात मूट है।
user7116

11

जब मैं दौड़ता हूँ

from c in Customers
where c.CustomerID == 1
where c.CustomerID == 2
where c.CustomerID == 3
select c

तथा

from c in Customers
where c.CustomerID == 1 &&
c.CustomerID == 2 &&
c.CustomerID == 3
select c customer table in linqpad

मेरी ग्राहक तालिका के खिलाफ यह उसी sql क्वेरी का उत्पादन करता है

-- Region Parameters
DECLARE @p0 Int = 1
DECLARE @p1 Int = 2
DECLARE @p2 Int = 3
-- EndRegion
SELECT [t0].[CustomerID], [t0].[CustomerName]
FROM [Customers] AS [t0]
WHERE ([t0].[CustomerID] = @p0) AND ([t0].[CustomerID] = @p1) AND ([t0].[CustomerID] = @p2)

इसलिए sql के अनुवाद में कोई अंतर नहीं है और आप पहले से ही अन्य उत्तरों में देख चुके हैं कि कैसे उन्हें लंबोदर अभिव्यक्तियों में परिवर्तित किया जाएगा


ठीक है, तो आप यह कहना चाहते हैं कि अगर मैं इनमें से किसी का भी उपयोग करता हूं तो इसका कोई प्रदर्शन प्रभाव नहीं होगा?
बिमल दास

वास्तव में क्लॉस की जंजीर कहां है। इसलिए, इससे कोई फर्क नहीं पड़ता कि आप इसे कैसे लिखते हैं। कोई प्रदर्शन अंतर नहीं है।
hastrb

3

हुड के नीचे देखते हुए, दोनों कथन अलग-अलग क्वेरी अभ्यावेदन में बदल जाएंगे। पर निर्भर करता है QueryProviderकी Collection, इस दूर अनुकूलित किया जा सकता है या नहीं।

जब यह एक लाइन-टू-ऑब्जेक्ट कॉल होता है, तो कई जहां क्लॉज़ IEnumerables की एक श्रृंखला का नेतृत्व करेंगे जो एक-दूसरे को पढ़ते हैं। सिंगल-क्लॉज फॉर्म का उपयोग करने से यहां प्रदर्शन में मदद मिलेगी।

जब अंतर्निहित प्रदाता इसे एसक्यूएल स्टेटमेंट में तब्दील करता है, तो संभावना अच्छी है कि दोनों वेरिएंट एक ही स्टेटमेंट बनाएंगे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.