LINQ शैली वरीयता [बंद]


21

मैं अपने हर दिन प्रोग्रामिंग में लाइनक्यू का उपयोग करने के लिए आया हूं। वास्तव में, मैं शायद ही कभी, अगर एक स्पष्ट लूप का उपयोग करता हूं। हालाँकि, मैंने पाया है कि मैं SQL को सिंटैक्स की तरह उपयोग नहीं करता। मैं सिर्फ विस्तार कार्यों का उपयोग करता हूं। इसलिए बल्कि तब कहना:

from x in y select datatransform where filter 

मैं उपयोग करता हूं:

x.Where(c => filter).Select(c => datatransform)

LINQ की कौन सी शैली आपको पसंद है और आपकी टीम के अन्य लोग किसके साथ सहज हैं?


5
यह ध्यान देने योग्य है कि आधिकारिक एमएस रुख यह है कि क्वेरी सिंटैक्स बेहतर है।
R0MANARMY

1
अंतत: इससे कोई फर्क नहीं पड़ता। क्या मायने रखता है कि कोड समझ में आता है। एक रूप एक मामले में बेहतर हो सकता है, दूसरा एक अलग मामले में। इसलिए उस समय का उपयोग करें जो कभी उचित हो।
ChrisF

मेरा मानना ​​है कि आपके दूसरे उदाहरण को लैम्ब्डा सिंटैक्स कहा जाता है, जो कि मैं 95% समय का उपयोग करता हूं। अन्य 5% मैं क्वेरी सिंटैक्स का उपयोग करता हूं जो कि जब मैं जॉइन कर रहा होता हूं, तो मैं लैम्ब्डा सिंटैक्स जॉइन करने के लिए संक्रमण का प्रयास कर रहा हूं, लेकिन अन्य लोगों ने बताया कि यह गड़बड़ है।
मफिन मैन

जवाबों:


26

मुझे यह दुर्भाग्यपूर्ण लगता है कि MSDN प्रलेखन प्रति Microsoft का रुख यह है कि क्वेरी सिंटैक्स बेहतर है, क्योंकि मैं इसका उपयोग कभी नहीं करता, लेकिन मैं हर समय LINQ विधि सिंटैक्स का उपयोग करता हूं। मुझे अपने दिल की सामग्री के लिए एक-लाइनर प्रश्नों को बंद करने में सक्षम होना पसंद है। की तुलना करें:

var products = from p in Products
               where p.StockOnHand == 0
               select p;

सेवा मेरे:

var products = Products.Where(p => p.StockOnHand == 0);

जल्दी, कम लाइनों, और मेरी आँखों को साफ दिखता है। क्वेरी सिंटैक्स सभी मानक LINQ ऑपरेटर्स का समर्थन नहीं करता है। एक उदाहरण क्वेरी मैंने हाल ही में कुछ इस तरह से देखा:

var itemInfo = InventoryItems
    .Where(r => r.ItemInfo is GeneralMerchInfo)
    .Select(r => r.ItemInfo)
    .Cast<GeneralMerchInfo>()
    .FirstOrDefault(r => r.Xref == xref);

मेरी जानकारी के लिए, क्वेरी सिंटैक्स (संभव सीमा तक) का उपयोग करके इस क्वेरी को दोहराने के लिए यह इस तरह दिखेगा:

var itemInfo = (from r in InventoryItems
                where r.ItemInfo is GeneralMerchInfo
                select r.ItemInfo)
                .Cast<GeneralMerchInfo>()
                .FirstOrDefault(r => r.Xref == xref);

मेरे लिए अधिक पठनीय नहीं दिखता है, और आपको यह जानने की आवश्यकता होगी कि किसी भी तरह से सिंटैक्स का उपयोग कैसे किया जाए। व्यक्तिगत रूप से मैं वास्तव में घोषित शैली से मुग्ध हो गया हूं LINQ संभव बनाता है और किसी भी स्थिति में इसका उपयोग करता है जहां यह बिल्कुल संभव है - शायद कभी-कभी मेरे विरोध के लिए। बिंदु में मामला, विधि सिंटैक्स के साथ मैं ऐसा कुछ कर सकता हूं:

// projects an InventoryItem collection with total stock on hand for each GSItem
inventoryItems = repository.GSItems
    .Select(gsItem => new InventoryItem() {
        GSItem = gsItem,
        StockOnHand = repository.InventoryItems
            .Where(inventoryItem => inventoryItem.GSItem.GSNumber == gsItem.GSNumber)
            .Sum(r => r.StockOnHand)
     });

मुझे लगता है कि उपरोक्त कोड अच्छे दस्तावेज के बिना परियोजना में आने वाले किसी व्यक्ति के लिए समझना मुश्किल होगा, और अगर उनके पास LINQ में कोई ठोस पृष्ठभूमि नहीं है, तो वे इसे वैसे भी नहीं समझ सकते हैं। फिर भी, विधि सिंटैक्स कुछ बहुत शक्तिशाली क्षमता को उजागर करता है, जल्दी से (कोड की लाइनों के संदर्भ में) एक क्वेरी को कई संग्रह के बारे में समग्र जानकारी प्राप्त करने के लिए प्रोजेक्ट करता है जो अन्यथा बहुत सारे थकाऊ फॉरेक्स लूपिंग ले जाएगा। इस तरह से एक मामले में, जो आप इससे बाहर निकलते हैं, उसके लिए विधि सिंटैक्स अल्ट्रा कॉम्पैक्ट है। क्वेरी सिंटैक्स के साथ ऐसा करने की कोशिश करने से आपको जल्दी से जल्दी नुकसान हो सकता है।


वह कास्ट जिसे आप चयन के अंदर कर सकते हैं, लेकिन दुर्भाग्य से आप LINQ विधियों का उपयोग किए बिना शीर्ष X रिकॉर्ड लेने के लिए निर्दिष्ट नहीं कर सकते। यह उन जगहों पर विशेष रूप से कष्टप्रद है जहां आप जानते हैं कि आपको केवल एक ही रिकॉर्ड की आवश्यकता है और सभी क्वेरी को कोष्ठक में रखना है।
ज़िव

2
सिर्फ रिकॉर्ड के लिए आप कहां () के बजाय सेलेक्ट (x => x.ItemInfo) .OfType <GeneralMerchInfo> () का चयन कर सकते हैं (सेलेक्ट करें ()। कास्ट <>), जो मेरा मानना ​​है कि तेज़ है (2n का बड़ा O) के बजाय n * 2m मुझे लगता है)। लेकिन आप पूरी तरह से सही हैं, लैम्बडा सिंटैक्स पठनीयता के दृष्टिकोण से काफी बेहतर है।
एड जेम्स

16

मुझे आंख पर कार्यात्मक वाक्यविन्यास अधिक भाता है। एकमात्र अपवाद यह है कि मुझे दो से अधिक सेटों में शामिल होने की आवश्यकता है। द जॉइन () बहुत जल्दी पागल हो जाता है।


सहमत ... मैं बहुत अधिक है, जब शामिल होने के अलावा विस्तार विधियों से देखो और पठनीयता पसंद करते हैं। घटक विक्रेता (उदाहरण के लिए टेलरिक) विस्तार के तरीकों का बहुत उपयोग करते हैं। मैं जिस उदाहरण के बारे में सोच रहा हूं वह ASP.NET MVC में उनका रेड कंट्रोल है। उन का उपयोग / पढ़ने के लिए आपको विस्तार विधियों का उपयोग करके बहुत कुशल होने की आवश्यकता है।
कैच करता है

यह कहने के लिए आया था। मैं आमतौर पर लैम्बदास का उपयोग करता हूं जब तक कि इसमें शामिल न हो। एक बार शामिल होने के बाद, LINQ सिंटैक्स अधिक पठनीय हो जाता है।
शॉन

10

क्या एक और उत्तर जोड़ने में कभी देर हो गई है?

मैंने LINQ-to-Objects कोड का एक टन लिखा है और मैं कम से कम उस डोमेन में तर्क देता हूं कि जो भी सरल कोड के लिए उपयोग करता है - जो कि हमेशा डॉट-सिंटैक्स नहीं है, दोनों सिंटैक्स को समझने के लिए अच्छा है।

बेशक कई बार जब डॉट वाक्य रचना कर रहे हैं है जाने का रास्ता - दूसरों इन मामलों में से कई की व्यवस्था की है; हालाँकि, मुझे लगता है कि समझ में कमी आई है - एक बुरा रैप दिया है, यदि आप करेंगे। इसलिए मैं एक नमूना प्रदान करूँगा जहाँ मेरा मानना ​​है कि समझ उपयोगी है।

यहाँ एक अंक प्रतिस्थापन पहेली का हल है: (लिनक्यूपैड का उपयोग करके लिखा गया समाधान, लेकिन कंसोल ऐप में अकेला खड़ा हो सकता है)

// NO
// NO
// NO
//+NO
//===
// OK

var solutions =
    from O in Enumerable.Range(1, 8) // 1-9
                    //.AsQueryable()
    from N in Enumerable.Range(1, 8) // 1-9
    where O != N
    let NO = 10 * N + O
    let product = 4 * NO
    where product < 100
    let K = product % 10
    where K != O && K != N && product / 10 == O
    select new { N, O, K };

foreach(var i in solutions)
{
    Console.WriteLine("N = {0}, O = {1}, K = {2}", i.N, i.O, i.K);
}

//Console.WriteLine("\nsolution expression tree\n" + solutions.Expression);

... जो आउटपुट:

एन = 1, ओ = 6, के = 4

बहुत बुरा नहीं है, तर्क रैखिक रूप से बहता है और हम देख सकते हैं कि यह एक एकल सही समाधान के साथ आता है। यह पहेली हाथ से हल करने के लिए काफी आसान है: तर्क है कि 3>> N0, और O> 4 * एन का मतलब है 8> = O> = 4. 4. इसका मतलब है कि हाथ से परीक्षण करने के लिए अधिकतम 10 मामले हैं (2 के लिए N-by- 5 के लिए O)। मैं काफी भटक गया हूं - यह पहेली LINQ चित्रण प्रयोजनों के लिए पेश की गई है।

संकलक रूपांतरण

बहुत सारे कंपाइलर इसे समकक्ष डॉट-सिंटैक्स में अनुवाद करने के लिए करते हैं। सामान्य दूसरे और बाद के fromखंडों को SelectManyकॉल में बदल दिया जाता है, हमारे पास letक्लॉस होते हैं जो Selectअनुमानों के साथ कॉल बन जाते हैं, दोनों पारदर्शी-पहचानकर्ता का उपयोग करते हैं । जैसा कि मैं दिखाने वाला हूं, इन पहचानकर्ताओं को डॉट-सिंटैक्स में नाम देना उस दृष्टिकोण की पठनीयता से दूर ले जाता है।

मेरे पास इस कोड को डॉट सिंटैक्स में अनुवाद करने के लिए क्या संकलक है इसे उजागर करने के लिए एक चाल है। यदि आप ऊपर टिप्पणी की गई दो पंक्तियों को जोड़ते हैं और इसे फिर से चलाते हैं, तो आपको निम्न आउटपुट मिलेंगे:

एन = 1, ओ = 6, के = 4

सॉल्यूशन एक्सप्रेशन ट्री सिस्टम .inq.Eumumable + d_ b8.SelectMany (O => रेंज (1, 8), (O, N) => नया <> f _AnonymousType0 2(O = O, N = N)).Where(<>h__TransparentIdentifier0 => (<>h__TransparentIdentifier0.O != <>h__TransparentIdentifier0.N)).Select(<>h__TransparentIdentifier0 => new <>f__AnonymousType12 (<> H_ TransparentIdentifier0 = <> h _TransparentIdentifier0, NO = = = ((10 * <> h_ TransparentIdentifier0.N) + <> ज _TransparentIdentifier0.O)))। चुनें (<> h_ TransparentIdentifier1 => नई <> च _AnonymousType2 2(<>h__TransparentIdentifier1 = <>h__TransparentIdentifier1, product = (4 * <>h__TransparentIdentifier1.NO))).Where(<>h__TransparentIdentifier2 => (<>h__TransparentIdentifier2.product < 100)).Select(<>h__TransparentIdentifier2 => new <>f__AnonymousType32 (<> h_ TransparentIdentifier2 = <> ज _TransparentIdentifier2, कश्मीर = ( <> h_ TransparentIdentifier2.product 10%)))। कहाँ (<> ज _TransparentIdentifier3 => (((<> h_ TransparentIdentifier3.K! = <> ज _TransparentIdentifier3। <> h_ TransparentIdentifier2। <>h _TransparentIdentifier1। <> h_TransparentIdentifier0.O) andalso (<> ज _TransparentIdentifier3.K! = <> H_ TransparentIdentifier3। <> ज _TransparentIdentifier2। <> H_ TransparentIdentifier1। <> ज _TransparentIdentifier0.N)) andalso ((<> h_ TransparentIdentifier3। <> ज _TransparentIdentifier2। उत्पाद / 10) == <> h_ TransparentIdentifier3। <> ज _TransparentIdentifier2। <> h_ TransparentIdentifier1। <> ज _TransparentIdentifier0.O)))। चुनें (<> h_ TransparentIdentifier3 => नई <> च _AnonymousType4`3 (एन = < > h_ TransparentIdentifier3। <> h _TransparentIdentifier2। <> h_ TransparentIdentifier1। <> h _TransparentIdentifier0.N।O = <> h_ TransparentIdentifier3। <> H_TransparentIdentifier2। <> H_ TransparentIdentifier1। <> H _TransparentIdentifier0.O, K = <> h__TransparentIdentifier3.K)

प्रत्येक LINQ ऑपरेटर को एक नई लाइन पर रखते हुए, "unspeakable" आइडेंटिफायर्स का अनुवाद हम "बोल" कर सकते हैं, अनाम प्रकारों को उनके परिचित रूप में बदल सकते हैं और AndAlsoएक्सप्रेशन-ट्री लिंगो को बदलकर &&, परिवर्तनों को उजागर करने के लिए कंपाइलर एक समकक्ष पर पहुंच सकते हैं। में डॉट-सिंटैक्स:

var solutions = 
    Enumerable.Range(1,8) // from O in Enumerable.Range(1,8)
        .SelectMany(O => Enumerable.Range(1, 8), (O, N) => new { O = O, N = N }) // from N in Enumerable.Range(1,8)
        .Where(temp0 => temp0.O != temp0.N) // where O != N
        .Select(temp0 => new { temp0 = temp0, NO = 10 * temp0.N + temp0.O }) // let NO = 10 * N + O
        .Select(temp1 => new { temp1 = temp1, product = 4 * temp1.NO }) // let product = 4 * NO
        .Where(temp2 => temp2.product < 100) // where product < 100
        .Select(temp2 => new { temp2 = temp2, K = temp2.product % 10 }) // let K = product % 10
        .Where(temp3 => temp3.K != temp3.temp2.temp1.temp0.O && temp3.K != temp3.temp2.temp1.temp0.N && temp3.temp2.product / 10 == temp3.temp2.temp1.temp0.O)
        // where K != O && K != N && product / 10 == O
        .Select(temp3 => new { N = temp3.temp2.temp1.temp0.N, O = temp3.temp2.temp1.temp0.O, K = temp3.K });
        // select new { N, O, K };

foreach(var i in solutions)
{
    Console.WriteLine("N = {0}, O = {1}, K = {2}", i.N, i.O, i.K);
}

यदि आप चलाते हैं तो आप पुष्टि कर सकते हैं कि यह फिर से आउटपुट करता है:

एन = 1, ओ = 6, के = 4

... लेकिन क्या आप कभी इस तरह का कोड लिखेंगे?

मैं जवाब देना चाहता हूँ NONBHN (न केवल नहीं, बल्कि नर्क नहीं!) - क्योंकि यह अभी बहुत जटिल है। यकीन है कि आप "temp0" .. "temp3" की तुलना में कुछ और अधिक सार्थक पहचानकर्ता के साथ आ सकते हैं, लेकिन मुद्दा यह है कि वे कोड में कुछ भी नहीं जोड़ते हैं - वे कोड को बेहतर प्रदर्शन नहीं करते हैं, वे नहीं करते हैं कोड को बेहतर पढ़ें, वे केवल कोड को बदसूरत करते हैं, और यदि आप इसे हाथ से कर रहे हैं, तो इसमें कोई संदेह नहीं है कि आप इसे सही होने से पहले एक या तीन बार गड़बड़ कर देंगे। इसके अलावा, "नाम का खेल" खेलना सार्थक पहचानकर्ताओं के लिए काफी कठिन है, इसलिए मैं नाम-खेल से उस ब्रेक का स्वागत करता हूं जो कंपाइलर मुझे क्वेरी की समझ प्रदान करता है।

आपके लिए गंभीरता से लेने के लिए यह पहेली नमूना वास्तविक रूप से पर्याप्त नहीं हो सकता है ; हालाँकि, अन्य परिदृश्य मौजूद हैं जहाँ क्वेरी समझ चमक है:

  • की जटिलता Joinऔर GroupJoin: क्वेरी कॉम्प्रिहेंशन में रेंज वैरिएबल्स की स्कोपिंग उन joinगलतियों को बदल देती है जो कंप्रीहेंशन सिंटैक्स में कंपाइल-टाइम त्रुटियों में अन्यथा डॉट-सिंटैक्स में संकलित हो सकती हैं।
  • किसी भी समय कंपाइलर ट्रांसफॉर्मेशन ट्रांसफॉर्मर में एक पारदर्शी-पहचानकर्ता का परिचय देगा, कॉम्प्रिहेंशन सार्थक हो जाएगा। इसमें निम्न में से किसी का उपयोग शामिल है: एकाधिक fromखंड, joinऔर join..intoखंड और letखंड।

मैं अपने गृहनगर में एक से अधिक इंजीनियरिंग की दुकान के बारे में जानता हूं, जिसमें कम्‍प्रेशन सिंटैक्स है। मुझे लगता है कि यह एक समझदार वाक्य रचना के रूप में एक दया है, लेकिन एक उपकरण और उस पर एक उपयोगी है। मुझे लगता है कि यह कहना बहुत पसंद है, "ऐसी चीजें हैं जो आप एक पेचकश के साथ कर सकते हैं जो आप एक छेनी के साथ नहीं कर सकते। क्योंकि आप छेनी के रूप में एक पेचकश का उपयोग कर सकते हैं, तो राजा के अधीन छेनी पर प्रतिबंध लगा दिया जाता है।"


-1: वाह। ओपी थोड़ी सलाह देख रहा था। आपने एक उपन्यास पर मंथन किया! क्या आप इसे थोड़ा कसने का मन करेंगे?
जिम जी।

8

मेरी सलाह है कि क्वेरी एक्सप्रेशन तनाव सिंटैक्स का उपयोग करें जब संपूर्ण एक्सप्रेशन को सिंटेन्शन सिंटैक्स में किया जा सकता है। यह है, मैं पसंद करेंगे:

var query = from c in customers orderby c.Name select c.Address;

सेवा मेरे

var query = customers.OrderBy(c=>c.Name).Select(c=>c.Address);

लेकिन मैं पसंद करूंगा

int count = customers.Where(c=>c.City == "London").Count();

सेवा मेरे

int count = (from c in customers where c.City == "London" select c).Count();

काश, हम कुछ वाक्य-विन्यास के साथ आए होते, जिसने दोनों को मिलाने के लिए इसे अच्छा बना दिया। कुछ इस तरह:

int count = from c in customers 
            where c.City == "London" 
            select c 
            continue with Count();

लेकिन दुख की बात है कि हमने नहीं किया।

लेकिन मूल रूप से, यह वरीयता की बात है। वह करें जो आपको और आपके सहकर्मियों को बेहतर लगे।


3
वैकल्पिक रूप से आप अन्य LINQ ऑपरेटर कॉल से एक समझ को "परिचय समझाने वाले चर" के माध्यम से अलग करने पर विचार कर सकते हैं। उदाहरण के लिए,var londonCustomers = from c in ...; int count = londonCustomers.Count();
devgeezer

3

एसक्यूएल की तरह शुरू करने के लिए एक अच्छा तरीका है। लेकिन जैसा कि यह सीमित है (यह सिर्फ उन निर्माणों का समर्थन करता है जो आपकी वर्तमान भाषा का समर्थन करती है) अंततः डेवलपर्स विस्तार-तरीकों की शैली में जाते हैं।

मैं यह नोट करना चाहूंगा कि कुछ मामले हैं जो एसक्यूएल जैसी शैली द्वारा आसानी से लागू किए जा सकते हैं।

इसके अलावा, आप दोनों तरीकों को एक क्वेरी में जोड़ सकते हैं।


2

जब तक मुझे एक चर मध्य मार्ग को परिभाषित करने की आवश्यकता नहीं होती तब तक मैं गैर-क्वेरी सिंटैक्स का उपयोग करता हूं

from x in list
let y = x.DoExpensiveCalulation()
where y > 42
select y

लेकिन मैं गैर-क्वेरी सिंटैक्स की तरह लिखता हूं

x.Where(c => filter)
 .Select(c => datatransform)

2

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


मुझे लगता है कि आप पाएंगे कि "क्वेरी कॉम्प्रिहेंशन" सिंटैक्स में पेज पर ऑर्डर उसी तरह का होता है जैसा कि ऑपरेशंस में होता है। LINQ SQL के विपरीत पहले "सिलेक्ट" नहीं करता है।
एरिक लिपर्ट

1

मुझे एक्सटेंशन फंक्शन भी पसंद है।

हो सकता है कि यह मेरे दिमाग में वाक्य रचना की एक छलांग से कम हो।

यह आंख के लिए और भी अधिक पठनीय लगता है, खासकर यदि आप तीसरे पक्ष के ढांचे का उपयोग कर रहे हैं, जिसमें लाइन एपी है।


0

यहाँ मेरे द्वारा अनुसरण किया गया अनुमान है:

जब आप जुड़ते हैं, तो lambdas पर LINQ अभिव्यक्ति को पसंद करें।

मुझे लगता है कि जुड़ने वाले लंबोदर गन्दे दिखते हैं और पढ़ना मुश्किल है।

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