C # 4.0 वैकल्पिक आउट / रेफरी तर्क


212

क्या C # 4.0 वैकल्पिक outया refतर्क देता है?


2
वेल, सी ++ ने उन्हें प्रभावी रूप से "आउट" मापदंडों के लिए रखा है - आपके पास एक पता तर्क हो सकता है जो कि अशक्त है और यह लाइब्रेरी कोड लिखने के लिए काफी सामान्य है जो केवल ऐसे रिटर्न संरचना को पॉप्युलेट करेगा यदि सूचक गैर-अशक्त है। यह C API में "वैकल्पिक तर्कों" के लिए शून्य का उपयोग करने के लिए एक मुहावरा है।
एंडी डेंट

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

5
शायद यह इस बात से कोई मतलब नहीं है कि चीजों को कैसे लागू किया जाता है या वास्तव में एक वैकल्पिक पैरामीटर क्या है। लेकिन जैसा कि रोमकिन ने कहा, "वैकल्पिक आउट दलीलें" होना वास्तव में अच्छा होगा - यह कि सीएलआर के बजाय अंग्रेजी में पार्स करें और यह उचित और आईएमओ में वांछनीय हो जाए।
एडम टोली

9
C # नहीं करता है, लेकिन VB.NET करता है।
जेसन

5
यह पीट-पीटकर मार डाला गया है, हालांकि, मैं मदद नहीं कर सकता लेकिन वैकल्पिक समर्थन के लिए अपने समर्थन का उल्लेख कर सकता हूं। मैं काफी एक की स्थापना के माध्यम से संदर्भ द्वारा वैकल्पिक तर्क के आदी हो गए nullडिफ़ॉल्ट ( मैं PHP से आते हैं ) और के लिए परीक्षण null(तर्क को आबाद करने के साथ आगे बढ़ना है, उन परिचित के लिए लगता हैpreg_match() ) वैसे भी, जब मैं एक तकनीकी बिंदु से सहमत हैं कि यह वर्तमान में हो सकता है असंभव और PHP और C # बल्कि अतुलनीय हैं, यह अभी भी उपलब्ध होने के लिए एक " अच्छा " उपकरण होगा।
डेन लैग

जवाबों:


93

जैसा कि पहले ही उल्लेख किया गया है, यह बस अनुमति नहीं है और मुझे लगता है कि यह बहुत अच्छा अर्थ देता है। हालाँकि, कुछ और विवरणों को जोड़ने के लिए, यहाँ C # 4.0 विनिर्देशन , धारा 21.1 का एक उद्धरण है :

कंस्ट्रक्टरों के औपचारिक मापदंडों, विधियों, इंडेक्सरों और प्रतिनिधि प्रकारों को वैकल्पिक घोषित किया जा सकता है:

निश्चित-पैरामीटर:
    विशेषताएँ ऑप्ट -पैरामीटर-संशोधक ऑप्ट प्रकार पहचानकर्ता डिफ़ॉल्ट-तर्क ऑप्ट
डिफ़ॉल्ट-तर्क:
    = अभिव्यक्ति

  • डिफ़ॉल्ट-तर्क के साथ एक निश्चित पैरामीटर एक वैकल्पिक पैरामीटर है , जबकि डिफ़ॉल्ट-तर्क के बिना एक निश्चित पैरामीटर एक आवश्यक पैरामीटर है
  • औपचारिक-पैरामीटर-सूची में एक वैकल्पिक पैरामीटर के बाद एक आवश्यक पैरामीटर दिखाई नहीं दे सकता है ।
  • एक refया outपैरामीटर में एक डिफ़ॉल्ट-तर्क नहीं हो सकता है ।

वैकल्पिक रूप से, आप एक रेफ / आउट पैरामीटर के साथ एक अधिभार बना सकते हैं। हां, आपके पास दो फ़ंक्शन परिभाषाएँ होंगी, लेकिन यह आपको पूरा करने के बाद क्या करेगा
चाड

201

नहीं।

वर्कअराउंड एक अन्य विधि के साथ ओवरलोड करना है जिसमें पैरामीटर बाहर / रेफरी नहीं है, और जो आपके वर्तमान तरीके को कॉल करता है।

public bool SomeMethod(out string input)
{
    ...
}

// new overload
public bool SomeMethod()
{
    string temp;
    return SomeMethod(out temp);
}

अद्यतन: यदि आपके पास C # 7.0 है , तो आप सरल कर सकते हैं:

// new overload
public bool SomeMethod()
{
    return SomeMethod(out _);    // declare out as an inline discard variable
}

(साभार @Oskar / @Reiner इसे इंगित करने के लिए।)


6
अस्थायी / डमी घोषित करने से अधिक सुरुचिपूर्ण समाधान के लिए कोई विचार?
लुई राइस

20
उसके बारे में क्या सुरुचिपूर्ण नहीं है? मुझे पूरी तरह से सभ्य लगता है।
न्यूट्रिनो

27
शायद सभ्य, लेकिन सुरुचिपूर्ण निश्चित रूप से एक और लीग पर है। तथ्य यह है कि कोई बेहतर समाधान नहीं है इसका मतलब यह नहीं है कि यह डिक्री द्वारा अत्याधुनिक है।
ओ ० '।

7
@ O0 'पर पकड़ो। सी # 7.0 में आप यह करने के लिए सक्षम हो जाएगा: return SomeMethod(out string temp)। यहाँ और देखें: blogs.msdn.microsoft.com/dotnet/2016/08/24/…
Oskar

7
C # 7.0 में आप एक अस्थायी राइट-ओनली वैरिएबल का उपयोग कर सकते हैं जैसे:return SomeMethod(out _);
रीनर

64

नहीं, लेकिन एक और बढ़िया विकल्प यह है कि विधि वैकल्पिक मापदंडों के लिए जेनेरिक टेम्प्लेट क्लास का उपयोग निम्न प्रकार से कर रही है:

public class OptionalOut<Type>
{
    public Type Result { get; set; }
}

तो आप इसे निम्नानुसार उपयोग कर सकते हैं:

public string foo(string value, OptionalOut<int> outResult = null)
{
    // .. do something

    if (outResult != null) {
        outResult.Result = 100;
    }

    return value;
}

public void bar ()
{
    string str = "bar";

    string result;
    OptionalOut<int> optional = new OptionalOut<int> ();

    // example: call without the optional out parameter
    result = foo (str);
    Console.WriteLine ("Output was {0} with no optional value used", result);

    // example: call it with optional parameter
    result = foo (str, optional);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional.Result);

    // example: call it with named optional parameter
    foo (str, outResult: optional);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional.Result);
}

19
यह एक बहुत ही उचित समाधान है, लेकिन एक बात का ध्यान रखें कि कंपाइलर आवश्यकता को लागू नहीं करेगा कि विधि से बाहर निकलने से पहले आउट पैरामीटर को सौंपा जाए।
केन स्मिथ

2
मुझे यह पसंद है, लेकिन यदि आप एक नया वर्ग नहीं बनाना चाहते हैं, तो आप इसे एकल तत्व सरणी में पास करके अनुकरण कर सकते हैं।
zumalifeguard

30

वास्तव में ऐसा करने का एक तरीका है जिसकी अनुमति C # है। यह C ++ पर वापस आ जाता है, और C # की अच्छी ऑब्जेक्ट-ओरिएंटेड संरचना का उल्लंघन करता है।

उपयोग के साथ इस विधि का उपयोग करें!

यहां आप एक वैकल्पिक पैरामीटर के साथ अपने कार्य को घोषित करने और लिखने का तरीका बता रहे हैं:

unsafe public void OptionalOutParameter(int* pOutParam = null)
{
    int lInteger = 5;
    // If the parameter is NULL, the caller doesn't care about this value.
    if (pOutParam != null) 
    { 
        // If it isn't null, the caller has provided the address of an integer.
        *pOutParam = lInteger; // Dereference the pointer and assign the return value.
    }
}

फिर फ़ंक्शन को इस तरह से कॉल करें:

unsafe { OptionalOutParameter(); } // does nothing
int MyInteger = 0;
unsafe { OptionalOutParameter(&MyInteger); } // pass in the address of MyInteger.

इसे संकलित करने के लिए, आपको प्रोजेक्ट विकल्पों में असुरक्षित कोड को सक्षम करना होगा। यह वास्तव में हैकी समाधान है जिसका उपयोग आमतौर पर नहीं किया जाना चाहिए, लेकिन यदि आप कुछ अजीब, रहस्यमय, रहस्यमय, प्रबंधन से प्रेरित निर्णय के लिए चाहते हैं, तो वास्तव में C # में एक वैकल्पिक आउट पैरामीटर की आवश्यकता है, तो यह आपको बस ऐसा करने की अनुमति देगा।


6

ICYMI: C # 7.0 के लिए नई सुविधाओं को शामिल किया गया है , "डिस्कार्ड" को अब _ के रूप में बाहर मापदंडों के रूप में अनुमति दी गई है, आपको उन मापदंडों की अनदेखी करने की अनुमति देता है जिनके बारे में आप परवाह नहीं करते हैं:

p.GetCoordinates(out var x, out _); // I only care about x

PS यदि आप "एक्स वर्जन" के भाग से भी भ्रमित हैं, तो लिंक पर "आउट वेरिएबल्स" के बारे में नई सुविधा पढ़ें।


यह _ या * "p.GetCoordinates (int int x, out *); // मैं केवल x के बारे में परवाह करता हूं"
Onur Topal

ऐसा लगता है कि मैं दस्तावेज़ का एक पुराना संस्करण देख रहा था।
ओनूर टोपल

2

नहीं, लेकिन आप Actionएक विकल्प के रूप में एक प्रतिनिधि (जैसे ) का उपयोग कर सकते हैं ।

रॉबिन आर के जवाब से प्रेरित होकर एक ऐसी स्थिति का सामना करना पड़ा जहां मुझे लगा कि मैं एक वैकल्पिक आउट पैरामीटर चाहता हूं, मैंने इसके बजाय एक Actionप्रतिनिधि का उपयोग किया । मैंने Action<int>अंतर और समानता दिखाने के लिए उनके उदाहरण कोड को संशोधित करने के लिए उधार लिया है :

public string foo(string value, Action<int> outResult = null)
{
    // .. do something

    outResult?.Invoke(100);

    return value;
}

public void bar ()
{
    string str = "bar";

    string result;
    int optional = 0;

    // example: call without the optional out parameter
    result = foo (str);
    Console.WriteLine ("Output was {0} with no optional value used", result);

    // example: call it with optional parameter
    result = foo (str, x => optional = x);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional);

    // example: call it with named optional parameter
    foo (str, outResult: x => optional = x);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional);
}

इसका यह लाभ है कि स्रोत में एक सामान्य इंट के रूप में वैकल्पिक चर दिखाई देता है (कंपाइलर इसे क्लोजर क्लास में लपेटता है, बजाय इसके कि हम इसे उपयोगकर्ता-निर्धारित कक्षा में स्पष्ट रूप से लपेटें)।

चर को स्पष्ट रूप से आरंभ करने की आवश्यकता है क्योंकि कंपाइलर यह नहीं मान सकता है कि Actionफ़ंक्शन कॉल से बाहर निकलने से पहले कॉल किया जाएगा।

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


0

सी # 6.0 और उससे कम के लिए आउट पैरामीटर के साथ कॉल करने के लिए आउट पैरामीटर के बिना एक अधिभार विधि का उपयोग करें। मुझे यकीन नहीं है कि .NET कोर के लिए C # 7.0 क्यों इस धागे के लिए सही उत्तर है, जब यह विशेष रूप से पूछा गया था कि क्या C # 4.0 में वैकल्पिक आउट पैरामीटर हो सकता है। जवाब न है!


-2

इस बारे में क्या?

public bool OptionalOutParamMethod([Optional] ref string pOutParam)
{
    return true;
}

आपको अभी भी C # से पैरामीटर के लिए एक मान पास करना है लेकिन यह एक वैकल्पिक रेफ परम है।


8
"आपको अभी भी C # से पैरामीटर का मान पास करना है ..." यह इसे वैकल्पिक नहीं बनाता है।
आर्टुरो टॉरेस सैंचेज़

C # [Optional]एनोटेशन को अनदेखा करता है । यह मदद नहीं करता है।
टूलमेकर

-4
void foo(ref int? n)
{
    return null;
}

1
कृपया सभी को आसानी से अवधारणा को समझने के लिए अपने कोड पर कुछ स्पष्टीकरण जोड़ें
टेकस्पाइडर

1
यद्यपि यह कोड प्रश्न का उत्तर दे सकता है, क्यों और / या कैसे का उत्तर देता है के संबंध में अतिरिक्त संदर्भ प्रदान करने से इसके दीर्घकालिक मूल्य में काफी सुधार होगा। कृपया कुछ स्पष्टीकरण जोड़ने के लिए अपने उत्तर को संपादित करें।
टोबी स्पाईट

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