स्पष्ट रूप से एक आउट तर्क को कैसे त्यागें?


99

मैं एक कॉल कर रहा हूँ:

myResult = MakeMyCall(inputParams, out messages);

लेकिन मैं वास्तव में संदेशों की परवाह नहीं करता। यदि यह एक इनपुट पैरामीटर था, तो मुझे इस बात की परवाह नहीं थी कि मैं बस एक अशक्त में गुजरता हूँ। अगर यह वापसी थी तो मुझे इस बात की परवाह नहीं थी कि मैं इसे छोड़ दूंगा।

क्या बाहर के साथ ऐसा ही कुछ करने का एक तरीका है, या क्या मुझे एक चर घोषित करने की आवश्यकता है जिसे मैं तब अनदेखा कर दूंगा?


इसी तरह का प्रश्न यहां: stackoverflow.com/questions/2870544/…
डन


धन्यवाद! शर्म की बात है कि यह नवीनतम संस्करण में नहीं है।
एंड्रयू डकर

जवाबों:


99

C # 7.0 से शुरू करते हुए, मानकों की अनदेखी करने के साथ-साथ उन्हें अनदेखा करना भी संभव है।

public void PrintCoordinates(Point p)
{
    p.GetCoordinates(out int x, out int y);
    WriteLine($"({x}, {y})");
}

public void PrintXCoordinate(Point p)
{
    p.GetCoordinates(out int x, out _); // I only care about x
    WriteLine($"{x}");
}

स्रोत: https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7s/


1
दुर्भाग्य से, यह C # 7 (अप्रैल 2017 के अनुसार) में शामिल नहीं है।
tia

2
@tia। मैंने अपना उत्तर अपडेट कर दिया है। जाहिर है, वाइल्डकार्ड वर्ण से बदल गया था *करने के लिए _। माफ़ कीजिए इतना समय लग गया।
नोलोनार

14
उन्हें out voidसिंटैक्स के लिए उपयोग करने के लिए अपने विचार के साथ अटक जाना चाहिए था , और अंडरस्कोर एक विषम विकल्प की तरह लगता है।
डेविड एंडरसन

1
@ डेविडअंडरसन-डीसीओएम जबकि मैं अंडरस्कोर का कोई प्रशंसक नहीं हूं, मुझे लगता है कि उन्हें अधिभार संकल्प के प्रकार के नाम की आवश्यकता है।
जोनाथन एलन

ऐसा लगता है कि यह अभी भी एक पैरामीटर बनाता है, क्योंकि मैं _ = {a value};बिना किसी संकलन त्रुटियों के फ़ंक्शन कॉल के बाद लाइन जोड़ सकता हूं ।
बिप 901

37

दुर्भाग्य से आपको कुछ पास करने की आवश्यकता होती है क्योंकि इसे सेट करने के लिए विधि की आवश्यकता होती है। इसलिए आप इसे नहीं भेज सकते nullक्योंकि इसे सेट करने के लिए आवश्यक विधि को उड़ा दिया जाएगा।

कुरूपता को छिपाने के लिए एक तरीका उस विधि को दूसरी विधि से लपेटना होगा जो outआपके लिए पैरामीटर को पसंद करती है:

String Other_MakeMyCall(String inputParams)
{
    String messages;

    return MakeMyCall(inputParams, out messages);
}

तब आप उन मापदंडों के Other_MakeMyCallसाथ फेल होने के बिना कॉल कर सकते हैं जिनकी outआपको आवश्यकता नहीं है।


37

आपको एक चर घोषित करना होगा जिसे आप तब अनदेखा कर देंगे। यह आमतौर पर TryParse (या TryWhatever) पैटर्न के साथ मामला है, जब इसका उपयोग उपयोगकर्ता इनपुट की वैधता का परीक्षण करने के लिए किया जाता है (जैसे कि इसे एक संख्या के रूप में पार्स किया जा सकता है?) वास्तविक पार्स मूल्य के बारे में परवाह किए बिना।

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


एक व्यावहारिक विरोधी पैटर्न के अधिक
जोर्डेल

11

यदि मूल कार्य इस प्रकार घोषित किया जाता है:

class C
{
    public Result MakeMyCall(Object arg, out List<String> messages);
}

आप इस तरह से एक एक्सटेंशन विधि की घोषणा कर सकते हैं:

static class CExtension
{
    public static Result MakeMyCall(this C obj, Object arg)
    {
        List<String> unused;
        return obj.MakeMyCall(arg, out unused);
    }
}

एक्सटेंशन विधि एक अधिभार की तरह व्यवहार करेगी जो आउट पैरामीटर को वैकल्पिक बनाती है।


4

Visual Basic कंपाइलर डमी वैरिएबल बनाकर ऐसा करता है। C # कर सकता है, यदि आप Microsoft को एक अच्छा विचार दे सकते हैं।


0

यदि messagesलागू होने का वर्ग है IDisposable, तो आपको इसे अनदेखा नहीं करना चाहिए। निम्नलिखित दृष्टिकोण की तरह कुछ पर विचार करें (क्योंकि मैं # थोड़ी देर में C # नहीं लिखा है) सही ढंग से सही नहीं हो सकता है।

using (FooClass messages) {
    myResult = MakeMyCall(inputParams, messages);
}

एक बार usingब्लॉक के बाहर , messagesअपने आप निपट जाएगा।


1
दिलचस्प। लेकिन क्या आपको स्टेटमेंट का उपयोग करके वैरिएबल को इनिशियलाइज़ नहीं करना है?
ओरेगनगॉस्ट

1
@OregonGhost: हाँ, आप करते हैं। और यदि आप का उपयोग कर बयान के भीतर चर के मूल्य को बदलते हैं, यह अभी भी मूल मूल्य है जो निपटाया जाता है।
जॉन स्कीट

@JonSkeet समझ नहीं सका कि यह अभी भी मूल मूल्य है जो निपटाया गया है।
ओरखान अलीखानोव

@OrhanAlikhanov: संकलक मूल रूप से usingकथन की शुरुआत में चर की एक प्रति लेता है । इसलिए ब्लॉक के भीतर उस वैरिएबल के मूल्य को बदलने से वह परिवर्तन नहीं होता है, जो वस्तु का निस्तारण हो जाता है।
जॉन स्कीट

वैसे, वहाँ होना चाहिए out messages
ओरखान अलीखानोव

0

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

MyMessagesType messages;
myResult = MakeMyCall(inputParams, out messages); 

आमतौर पर, आप कॉल के बाद 'संदेशों' को अनदेखा कर सकते हैं - जब तक कि 'संदेशों' को किसी कारण से निपटाने की आवश्यकता नहीं होती है, जैसे कि सीमित सिस्टम संसाधनों का उपयोग, जिस स्थिति में आपको कॉल करना चाहिए (डिस्पोज़):

messages.Dispose();

यदि यह महत्वपूर्ण मात्रा में मेमोरी का उपयोग कर सकता है और यह थोड़ी देर के लिए स्कोप में रहने वाला है, तो संभवतया इसे अशक्त करने के लिए सेट किया जाना चाहिए यदि यह एक संदर्भ प्रकार है या किसी नए डिफ़ॉल्ट उदाहरण के लिए यदि यह मान टाइप है, तो यह है कि कचरा कलेक्टर स्मृति को पुनः प्राप्त कर सकते हैं:

messages = null; // Allow GC to reclaim memory for reference type.

messages = new MyMessageType(); // Allow GC to reclaim memory for value type.

0

इस मामले में मैंने कॉनकरेन्डो के लिए एक सामान्य विस्तार विधि बनाई जिसमें कोई हटाएं या निकालें विधि नहीं है।

//Remove item from list and ignore reference to removed item
public static void TryRemoveIgnore<K,T>(this ConcurrentDictionary<K,T> dictionary, K key)
{
    T CompletelyIgnored;
    dictionary.TryRemove(key, out CompletelyIgnored);
}

जब समवर्ती छाया के उदाहरण से कॉल किया जाता है:

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