2012-03-21 18 views
7

लिंक के साथ, रेंज वेरिएबल (ई) को सरणी/संग्रह (एएमपीएस) से स्पष्ट रूप से टाइप किया जा सकता है, लेकिन एक फोरैच स्टेटमेंट वही कीवर्ड के बिना वही काम नहीं कर सकता है, या प्रकार। ऐसा क्यों है?लिंक इम्प्लिसी टाइप टाइप रेंज वेरिएबल

ex1 में संकलक जानता है कि ई प्रकार का प्रकार है, बिना किसी कीवर्ड या कुछ भी दिए। EX2 में फ़ोरैच लूप एक ही चीज़ क्यों नहीं कर सकता है, आपको प्रकार प्रदान करना होगा (चाहे उसका var या कुछ प्रकार)।

ex1।

Employee[] emps = {new Employee (1, "Daniel", "Cooley", 7, 57.98M }; 

    public void SortByLastname() 
    { 
     var sortedByLastname = 
      from e in emps 
      orderby e.LastName 
      select e.FirstName; 
    } 

ex2।

 foreach (Employee empl in emps) 
     { 
      Console.WriteLine("Employee " + empl); 
     } 

यह विश्लेषण खत्म हो सकता है लेकिन मैं इस मामले के नीचे क्यों पहुंचने की कोशिश कर रहा हूं।

उत्तर बहुत अच्छी तरह से हो सकता है कि लिंक वैरिएबल सिंटैक्स को श्रेणी चर के प्रकार को कम करने के लिए सेट किया गया है और foreach statment नहीं है। क्या कोई यह समझाने में मदद कर सकता है कि यह क्यों है?

+0

मुझे विश्वास नहीं है कि ex1 सही है - यह संकलित नहीं होगा। क्या आपका मतलब कर्मचारी नहीं है [] emps = new [] {नया कर्मचारी (...)}; ... और आपके दूसरे उदाहरण में ... foreach को टी में टी को डालने में कोई समस्या नहीं होनी चाहिए [] या किसी भी IENumerable ... इसलिए मुझे यकीन नहीं है कि मैं उस समस्या को समझता हूं जिसका आप वर्णन कर रहे हैं। – Jeff

+0

क्षमा करें पहले यहां पोस्ट करें ताकि साइट कैसे काम करती है। हाँ दूसरा dexample पहले से संबंधित होने का इरादा नहीं है मेरे बुरे को केवल linq परिणाम के बजाय सरणी में सरणी डाल दिया जाना चाहिए था। – mgmedick

+0

मैंने इसे इंगित करने के लिए अपना कोड अपडेट किया है, और मेरा उत्तर :) –

उत्तर

3

कारण आप सूची क्योंकि यह (मूल रूप से) विस्तार तरीकों से टूट किया जा रहा है प्रकार है की जरूरत नहीं है। आप ex2 के पुनर्लेखन के लिए सक्षम होना चाहिए के रूप में:

emps.ForEach(empl=>Console.WriteLine("Employee " + empl); 

सूचना आपने अभी तक स्पष्ट प्रकार कहने के लिए के रूप में यह emps

से अनुमान लगाया है

तो EX1 नीचे करने के लिए टूट जाएगा की जरूरत नहीं है:

emps.OrderBy(e=>e.LastName).Select(e=>e.FirstName); 

इस बारे में बहुत अधिक समझने के लिए, मैं वास्तव में जॉन स्कीट्स पुस्तक C# In Depth Second Edition

+1

वाह त्वरित प्रतिक्रिया :) मैं यहां और अधिक बार आ रहा हूं। तो यह वास्तव में एक मुद्दा है कि linq कोड कैसे काम करता है। इसके पीछे जो भी कोड लिनक को सशक्त कर रहा है वह इसे कम करने में सक्षम है (जैसे अदृश्य var हमेशा होता है) जबकि foreach कथन नहीं है? क्या वो सही है? क्या यह linq के इंटरफ़ेस होने के साथ IEnumberable के साथ करना है, जबकि मैंने पढ़ा है कि वास्तव में foreach का इंटरफ़ेस नहीं है? सहायता के लिए धनयवाद। – mgmedick

+0

की तरह। मैं विस्तार विधियों और जेनेरिकों पर पढ़ने का सुझाव देता हूं और फिर दोनों प्रकार के अनुमान में कैसे इंटरैक्ट करते हैं। असल में, मेरे उदाहरण में, emps.OrderBy ... वास्तव में एक स्थिर विधि चला रहा है जो पहले पैरामीटर के रूप में emps को पास करता है। जिसका उपयोग शेष प्रकारों को जानने के लिए किया जाता है। यह यहां व्याख्या करने के लिए वास्तव में एक व्यापक विषय हो सकता है, इसलिए मैं यह जानने के लिए और अधिक समझने के लिए सुझाव दूंगा कि मैंने जो पुस्तक सुझाई है ... कम से कम उन विषयों पर कुछ Google खोजों का उल्लेख किया गया है जिनका मैंने उल्लेख किया है –

+0

ठीक है, इसलिए lamens linq वाक्यविन्यास सरणी वस्तु पर विस्तार विधियों का उपयोग कर रहा है। जबकि foreach वस्तु से अनजान है तो इसे प्रकार की जरूरत है। क्या मैं आधार से दूर हूं? lol – mgmedick

0

ऐसा लगता है कि 'empl' दूसरे उदाहरण में एक स्ट्रिंग है, क्योंकि LINQ कथन का चयन खंड ई। फर्स्टनाम कहते हैं। आप इसे कर्मचारी सूची में शामिल करना चाहते हैं, निम्नलिखित का उपयोग करें:

var sortedByLastname = 
    from e in emps 
    select e 
    orderby e.LastName; 
0

खरीदने के लिए सुझाव देता हूं, इसे भाषा निर्माण के साथ करना है चर प्रकार के उल्लंघन से। कारण-लूप वैर-कीवर्ड के बिना ऐसा नहीं कर सकता है क्योंकि foreach(var empl in list) और foreach(empl in list) अलग-अलग चीजों का मतलब है (मुझे यह भी यकीन नहीं है कि दूसरा कानूनी है)। पहला एक नया चर आवंटित करता है, जबकि दूसरा (यदि कानूनी) पहले से मौजूद चर का उपयोग करेगा (कारण का कारण सही ढंग से टाइप करना होगा)। हालांकि, LINQ निर्माण में इस तरह से बनाया गया है कि जब आप for e in list ई एक चर के रूप में बनाया गया है।

14

अद्यतन: This question was the subject of my blog on June 25th, 2012। महान सवाल के लिए धन्यवाद!


Linq के साथ, सीमा चर परोक्ष संग्रह से आ रही है से टाइप किया जा सकता है, लेकिन एक foreach बयान var कीवर्ड के बिना एक ही बात नहीं कर सकते।

यह सही है।

यह क्यों है?

मुझे कभी नहीं पता कि "क्यों" प्रश्नों का उत्तर देना है। तो मैं आपको एक अलग प्रश्न पूछने का नाटक करूंगा:

दो अलग-अलग तरीके हैं जिन्हें एक नामित चर को स्पष्ट रूप से टाइप किया जा सकता है। एक नामित स्थानीय चर, लूप वैरिएबल, फोरैच लूप वेरिएबल, या कथन वैरिएबल का उपयोग करके स्पष्ट रूप से "var" को इसके स्पष्ट प्रकार के लिए प्रतिस्थापित करके टाइप किया जा सकता है। एक लैम्ब्डा पैरामीटर या क्वेरी रेंज वैरिएबल को पूरी तरह से अपने प्रकार को छोड़कर टाइप किया जा सकता है।

सही।

यह एक असंगतता है। एक बुनियादी डिजाइन सिद्धांत यह है कि असंगतता से बचा जाना चाहिए क्योंकि यह भ्रमित है; उपयोगकर्ता स्वाभाविक रूप से मानता है कि एक असंगतता अर्थ व्यक्त करती है। क्या इन सुविधाओं को लगातार बनाया जा सकता है?

दरअसल, दो तरीके हैं जो वे लगातार बना सकते थे।

Func<double, double> f = (var x)=>Math.Sin(x); 
var query = from var customer in customers 
      join var order in orders on customer.Id equals ... 

सभी डिजाइन समझौते की एक श्रृंखला है: पहला, ताकि आप कह सकते हैं कि "var" की आवश्यकता के लिए हर जगह, है। यह स्थिरता परीक्षण को पूरा करता है लेकिन अब घबराहट और verbose लगता है।

x = 12; // Same as "int x = 12;" 
using(file = ...) ... 
for(i = 0; i < 10; ++i) ... 
foreach(c in customers) ... 

पहले तीन मामलों में हम अब अनजाने की "परोक्ष घोषित स्थानीय लोगों" सुविधा के बजाय "परोक्ष टाइप किया जोड़ लिया है:

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

हालांकि, foreach ब्लॉक में यह संदर्भ से स्पष्ट है कि एक स्थानीय चर पेश किया जा रहा है। हम बहुत अधिक भ्रम पैदा किए बिना यहां "var" को खत्म कर सकते हैं, क्योंकि "इन" को असाइनमेंट के लिए गलत नहीं माना जाता है।

ठीक है, तो चलो हमारे संभव सुविधाओं योग करते हैं:

  • फ़ीचर 1: हर जगह वर की आवश्यकता है।
  • फ़ीचर 2: कहीं भी var की आवश्यकता नहीं है।
  • फ़ीचर 3: लूप और usings के लिए, स्थानीय लोगों पर वर की आवश्यकता नहीं है, लेकिन छोरों, lambdas या सीमा चर
  • सुविधा 4 foreach: का उपयोग करने और foreach, लेकिन नहीं lambdas या सीमा चर छोरों के लिए स्थानीय लोगों पर वर की आवश्यकता होती है,

पहले दो में स्थिरता के लाभ हैं, लेकिन स्थिरता केवल एक कारक है। पहला एक गुंजाइश है। दूसरा एक बहुत गतिशील और भ्रमित है। तीसरे और चौथे लोग व्यावहारिक समझौते की तरह लगते हैं, हालांकि वे लगातार नहीं हैं।

सवाल तो यह है: foreach पाश चर अधिक एक स्थानीय चर या अधिक एक लैम्ब्डा पैरामीटर की तरह की तरह है? स्पष्ट रूप से यह एक स्थानीय चर की तरह है; वास्तव में, foreach loop निर्दिष्ट एक पुनर्लेखन के रूप में है जिसमें लूप चर एक स्थानीय चर बन जाता है।"फॉर" लूप के साथ स्थिरता के लिए, और फोरैच लूप के सी # 1.0 और सी # 2.0 उपयोग के साथ स्थिरता के लिए, जिसे किसी प्रकार का एक प्रकार की आवश्यकता होती है, हम विकल्प चार को विकल्प तीन से बेहतर चुनते हैं।

मुझे आशा है कि आपके प्रश्न का उत्तर दें। यदि नहीं, तो एक बहुत अधिक विशिष्ट सवाल पूछें।

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