सवाल एक अज्ञात विधि var को क्यों असाइन नहीं किया जा सकता है?


मेरे पास निम्न कोड है:

Func<string, bool> comparer = delegate(string value) {
    return value != "0";
};

हालांकि, निम्नलिखित संकलित नहीं है:

var comparer = delegate(string value) {
    return value != "0";
};

संकलक यह क्यों नहीं समझ सकता है Func<string, bool>? यह एक स्ट्रिंग पैरामीटर लेता है, और एक बूलियन देता है। इसके बजाय, यह मुझे त्रुटि देता है:

अज्ञात विधि को असाइन नहीं कर सकता   निहित रूप से टाइप किया गया स्थानीय चर।

मेरे पास एक अनुमान है और वह है अगर var संस्करण संकलितयदि मेरे पास निम्न था तो इसमें स्थिरता की कमी होगी:

var comparer = delegate(string arg1, string arg2, string arg3, string arg4, string arg5) {
    return false;
};

उपरोक्त समझ में नहीं आएगा क्योंकि Func <> केवल 4 तर्कों की अनुमति देता है (.NET 3.5 में, जो मैं उपयोग कर रहा हूं)। शायद कोई समस्या को स्पष्ट कर सकता है। धन्यवाद।


119
2018-02-11 04:17


मूल


आपके बारे में नोट करें 4 तर्क तर्क, .NET 4 में, Func<> 16 तर्कों को स्वीकार करता है। - Anthony Pegram
स्पष्टीकरण के लिए धन्यवाद। मैं .NET 3.5 का उपयोग कर रहा हूँ। - Marlon
संकलक को ऐसा क्यों लगता है कि यह एक है Func<string, bool>? वो ____ की तरह दीखता है Converter<string, bool> मेरे लिए! - Ben Voigt
के संभावित डुप्लिकेट सी # इनलाइन अज्ञात लैम्बडा या प्रतिनिधियों का उपयोग क्यों नहीं कर सकता? - nawfal
कभी-कभी मुझे वीबी याद आती है .. Dim comparer = Function(value$) value <> "0" - Slai


जवाब:


अन्य ने पहले से ही बताया है कि आप असीमित कई संभावित प्रतिनिधि प्रकार हैं जो आप हैं सकता है मतलब है; इसके बारे में इतना खास क्या है Func कि इसके बजाय डिफ़ॉल्ट होने का हकदार है Predicate या Action या कोई अन्य संभावना है? और, lambdas के लिए, यह स्पष्ट क्यों है कि अभिव्यक्ति वृक्ष रूप के बजाय, प्रतिनिधि फार्म का चयन करना है?

लेकिन हम यह कह सकते थे Func विशेष है, और एक लैम्ब्डा या अज्ञात विधि का अनुमानित प्रकार कुछ का Func है। हम अभी भी सभी प्रकार की समस्याएं हैं। निम्नलिखित मामलों के लिए आप किस प्रकार अनुमानित होना चाहते हैं?

var x1 = (ref int y)=>123;

कोई नहीं है Func<T> टाइप करें जो कुछ भी रेफरी लेता है।

var x2 = y=>123;

हम औपचारिक पैरामीटर के प्रकार को नहीं जानते हैं, हालांकि हम वापसी को जानते हैं। (या हम करते हैं? क्या रिटर्न int है? लंबा? छोटा? बाइट?)

var x3 = (int y)=>null;

हम रिटर्न प्रकार नहीं जानते हैं, लेकिन यह शून्य नहीं हो सकता है। वापसी का प्रकार कोई संदर्भ प्रकार या कोई शून्य मूल्य प्रकार हो सकता है।

var x4 = (int y)=>{ throw new Exception(); }

फिर, हम वापसी प्रकार, और इस बार यह नहीं जानते हैं कर सकते हैं शून्य हो

var x5 = (int y)=> q += y;

क्या यह एक शून्य-वापसी कथन लैम्बडा या ऐसा कुछ है जो q को सौंपा गया मान देता है? दोनों कानूनी हैं; हमें क्या चुनना चाहिए?

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

वह स्थिति जहां यह वास्तव में उपयोगी है:

var xAnon = (int y)=>new { Y = y };

क्योंकि उस चीज़ के लिए कोई "बोलने योग्य" प्रकार नहीं है। लेकिन हमारे पास हर समय यह समस्या है, और हम इस प्रकार को कम करने के लिए विधि प्रकार अनुमान का उपयोग करते हैं:

Func<A, R> WorkItOut<A, R>(Func<A, R> f) { return f; }
...
var xAnon = WorkItOut((int y)=>new { Y = y });

और अब विधि प्रकार अनुमान यह काम करता है कि func प्रकार क्या है।


132
2018-02-11 06:58



+1 महान जवाब। आपके नाम पर कॉल करने वाले सभी लोगों के साथ हम जानते थे कि आप दिखाएंगे। - The Scrum Meister
आप अपने एसओ उत्तरों को किसी पुस्तक में संकलित करने जा रहे हैं? मैं इसे खरीदूंगा :) - Matt Greer
मैं एसओ उत्तरों की एरिक लिपर्ट पुस्तक के प्रस्ताव को दूसरा स्थान देता हूं। सुझाए गए शीर्षक: "स्टैक से प्रतिबिंब" - Adam Rackis
@Eric: अच्छा जवाब, लेकिन यह है थोड़ा ऐसा कुछ ऐसा करने के लिए भ्रामक है जो संभव नहीं है, क्योंकि यह वास्तव में डी में पूरी तरह से ठीक काम करता है। यह सिर्फ इतना है कि आप प्रतिनिधि साहित्यियों को अपना स्वयं का प्रकार देने का विकल्प नहीं चुनते थे, और इसके बजाय उन्हें अपने संदर्भों पर निर्भर करते थे ... इसलिए IMHO जवाब होना चाहिए "क्योंकि हमने इसे बनाया है" किसी और चीज़ से ज्यादा। :) - Mehrdad
@AbstractDissonance: हमने सीमित संसाधनों के संदर्भ में लागत को माप लिया: डेवलपर्स और समय। यह जिम्मेदारी भगवान द्वारा नहीं दी गई थी; इसे डेवलपर डिवीजन के उपाध्यक्ष द्वारा लगाया गया था। धारणा है कि किसी भी तरह सी # टीम बजट प्रक्रिया को अनदेखा कर सकती है एक अजीब बात है। मैं आपको आश्वासन देता हूं, ट्रेडऑफ थे और अभी भी उन विशेषज्ञों के सावधान, विचारशील विचार से बने हैं जिनके पास सी # समुदायों ने इच्छा व्यक्त की थी, माइक्रोसॉफ्ट के लिए रणनीतिक मिशन, और डिजाइन में अपने स्वयं के उत्कृष्ट स्वाद। - Eric Lippert


केवल एरिक लिपर्ट निश्चित रूप से जानता है, लेकिन मुझे लगता है कि ऐसा इसलिए है क्योंकि प्रतिनिधि प्रकार का हस्ताक्षर विशिष्ट रूप से प्रकार का निर्धारण नहीं करता है।

अपने उदाहरण पर विचार करें:

var comparer = delegate(string value) { return value != "0"; };

यहां के लिए दो संभावित सम्मेलन हैं var होना चाहिए:

Predicate<string> comparer  = delegate(string value) { return value != "0"; };  // okay
Func<string, bool> comparer = delegate(string value) { return value != "0"; };  // also okay

किसको कंपाइलर अनुमान लगाया जाना चाहिए? एक या दूसरे को चुनने का कोई अच्छा कारण नहीं है। और हालांकि ए Predicate<T> कार्यात्मक रूप से एक के बराबर है Func<T, bool>, वे .NET प्रकार प्रणाली के स्तर पर अभी भी अलग-अलग प्रकार हैं। इसलिए संकलक प्रतिनिधि प्रकार को अनजाने में हल नहीं कर सकता है, और प्रकार अनुमान को विफल करना चाहिए।


27
2018-02-11 04:35



मुझे यकीन है कि माइक्रोसॉफ्ट में कुछ अन्य लोगों को भी निश्चित रूप से पता है। ;) लेकिन हाँ, आप एक मुख्य कारण से सहमत हैं, संकलन समय प्रकार निर्धारित नहीं किया जा सकता क्योंकि कोई भी नहीं है। भाषा विनिर्देश की धारा 8.5.1 विशेष रूप से टाइप किए गए चरम घोषणाओं में अज्ञात कार्यों को अस्वीकार करने के लिए इस कारण को हाइलाइट करती है। - Anthony Pegram
हां। और इससे भी बदतर, भेड़ के बच्चे के लिए हम यह भी नहीं जानते कि यह एक प्रतिनिधि प्रकार के लिए जा रहा है या नहीं; यह एक अभिव्यक्ति पेड़ हो सकता है। - Eric Lippert
किसी के लिए दिलचस्पी रखने के लिए, मैंने इसके बारे में थोड़ा और लिखा है कि कैसे सी # और एफ # इसके विपरीत है mindscapehq.com/blog/index.php/2011/02/23/... - itowlson
संकलक सिर्फ एक नया अद्वितीय प्रकार क्यों बना सकता है जैसे सी ++ अपने लैम्ब्डा फ़ंक्शन के लिए करता है - Weipeng L


एरिक लिपर्ट का पुराना है पद इसके बारे में वह कहता है

और वास्तव में सी # 2.0 विनिर्देश   इसे बुलाओ विधि समूह   अभिव्यक्ति और अज्ञात विधि   अभिव्यक्ति टाइपलेस अभिव्यक्तियां हैं   सी # 2.0 में, और लैम्ब्डा अभिव्यक्तियां शामिल हों   उन्हें सी # 3.0 में। इसलिए ऐसा है   उनके लिए "नग्न" दिखाई देने के लिए अवैध   एक निहित के दाहिनी तरफ   घोषणा।


6
2018-02-11 04:40



और यह भाषा विनिर्देश की धारा 8.5.1 द्वारा अंडरस्कोर किया गया है। एक प्रारंभिक टाइप किए गए स्थानीय चर के लिए उपयोग करने के लिए "प्रारंभकर्ता अभिव्यक्ति में संकलन-समय प्रकार होना चाहिए"। - Anthony Pegram
@ एंथनी: अपडेट के लिए धन्यवाद। - Brian Rasmussen


विभिन्न प्रतिनिधियों को विभिन्न प्रकार माना जाता है। उदाहरण के लिए, Action से अलग है MethodInvoker, और एक उदाहरण Action प्रकार के चर के लिए असाइन नहीं किया जा सकता है MethodInvoker

तो, एक अज्ञात प्रतिनिधि (या लैम्ब्डा) दिया गया है () => {}, यह एक है Action या ए MethodInvoker? कंपाइलर नहीं बता सकता है।

इसी तरह, अगर मैं एक प्रतिनिधि प्रकार घोषित करता हूं string तर्क और एक लौट रहा है bool, कंपाइलर कैसे जानता है कि आप वास्तव में चाहते थे Func<string, bool> मेरे प्रतिनिधि प्रकार के बजाय? यह प्रतिनिधि प्रकार का अनुमान नहीं लगा सकता है।


4
2018-02-11 04:34





निम्नलिखित बिंदु एमएसडीएन से लागू रूप से टाइप किए गए स्थानीय चर के बारे में हैं:

  1. var का उपयोग तब किया जा सकता है जब स्थानीय चर घोषित किया जाता है और उसी कथन में प्रारंभ किया जाता है; चर को शून्य, या किसी विधि समूह या अज्ञात फ़ंक्शन में प्रारंभ नहीं किया जा सकता है।
  2. Var कीवर्ड संकलक को प्रारंभिक विवरण के दाईं ओर अभिव्यक्ति से चर के प्रकार का अनुमान लगाने के लिए निर्देश देता है।
  3. यह समझना महत्वपूर्ण है कि विभिन्न कीवर्ड का अर्थ "संस्करण" नहीं है और यह इंगित नहीं करता है कि चर ढीला टाइप किया गया है, या देर से बाध्य है। इसका मतलब यह है कि संकलक सबसे उपयुक्त प्रकार निर्धारित करता है और असाइन करता है।

एमएसडीएन संदर्भ: लागू रूप से टाइप किए गए स्थानीय चर

बेनामी तरीकों के बारे में निम्नलिखित को ध्यान में रखते हुए:

  1. अनाम विधियां आपको पैरामीटर सूची को छोड़ने में सक्षम बनाती हैं।

एमएसडीएन संदर्भ: बेनामी तरीके

मुझे संदेह होगा कि चूंकि अज्ञात विधि में वास्तव में अलग-अलग विधि हस्ताक्षर हो सकते हैं, इसलिए संकलक सही ढंग से अनुमान लगाने में असमर्थ है कि असाइन करने के लिए सबसे उपयुक्त प्रकार क्या होगा।


1
2018-02-11 04:55





उसके बारे में कैसा है?

var item = new
    {
        toolisn = 100,
        LangId = "ENG",
        toolPath = (Func<int, string, string>) delegate(int toolisn, string LangId)
        {
              var path = "/Content/Tool_" + toolisn + "_" + LangId + "/story.html";
              return File.Exists(Server.MapPath(path)) ? "<a style=\"vertical-align:super\" href=\"" + path + "\" target=\"_blank\">execute example</a> " : "";
        }
};

string result = item.toolPath(item.toolisn, item.LangId);

0
2017-12-19 08:07