वहाँ एक "उलटा" करने के लिए अशक्त coalescing ऑपरेटर है? (… किसी भी भाषा में)


92

अशक्त सहानुभूति लगभग अनुवाद करती है return x, unless it is null, in which case return y

मुझे अक्सर जरूरत होती है return null if x is null, otherwise return x.y

मैं उपयोग कर सकता हूं return x == null ? null : x.y;

बुरा नहीं है, लेकिन nullबीच में हमेशा मुझे परेशान करता है - यह बहुत ही अच्छा लगता है। मैं कुछ पसंद करता हूँ return x :: x.y;, जहाँ निम्न प्रकार ::का मूल्यांकन किया जाता है यदि केवल वही है जो पहले नहीं है null

मैं इसे लगभग अशक्त सहसंरचना के विपरीत देखता हूं , जो एक स्वर के साथ मिश्रित है, इनलाइन null-check है, लेकिन मैं [ लगभग ] निश्चित हूं कि C # में ऐसा कोई ऑपरेटर नहीं है।

क्या ऐसी अन्य भाषाएं हैं जिनके पास ऐसा कोई ऑपरेटर है? यदि हां, तो इसे क्या कहा जाता है?

(मुझे पता है कि मैं इसके लिए C # में एक विधि लिख सकता हूं; मैं उपयोग करता हूं return NullOrValue.of(x, () => x.y);, लेकिन अगर आपके पास कुछ बेहतर है, तो मैं इसे भी देखना चाहता हूं।)


कुछ ने x? .Y in C # जैसे कुछ के लिए कहा है, लेकिन ऐसा कुछ भी मौजूद नहीं है।
एंथनी पेग्राम

1
@ एंथनी ओह, यह सुंदर होगा। धन्यवाद।
Jay

2
सी ++ में, यह व्यक्त करने के लिए पर्याप्त आसान होगा return x ? x.y : NULL। पॉली प्रकार को बुलियन में परिवर्तित करने के लिए याय!
फिल मिलर

1
@ नोवेलोक्रेट जो उन चीजों में से एक है जो मुझे C # में सबसे अधिक परेशान करता है, वह यह है कि यदि उन्होंने (यदि कुछ भी) = सच को छोड़कर C का पालन नहीं किया, तो वह (0, झूठा, अशक्त)
क्रिस मैरिसिक

2
@ क्रिस: सी। के बारे में एक सटीक बयान नहीं है। यदि आपके पास एक गैर-स्केलर चर (जैसे कि एक संरचना) है, तो आप उस स्थिति में इसका उपयोग नहीं कर सकते।
फिल मिलर

जवाबों:


62

नहीं है अशक्त-सुरक्षित dereferencing ऑपरेटर (?)। ग्रूवी में ... मुझे लगता है कि क्या आप के बाद कर रहे हैं कि के।

(इसे सुरक्षित नेविगेशन ऑपरेटर भी कहा जाता है ।)

उदाहरण के लिए:

homePostcode = person?.homeAddress?.postcode

यह शून्य देगा यदि person, person.homeAddressया person.homeAddress.postcodeअशक्त है।

(यह अब C # 6.0 में उपलब्ध है लेकिन पहले के संस्करणों में नहीं है)


1
ग्रूवी के पास "एल्विस ऑपरेटर" भी है, जो इसके अलावा अन्य डिफ़ॉल्ट मानों की अनुमति देता है null, जैसे:def bar = foo ?: "<null>"
क्रेग स्टंट्ज

28
मैं इस सुविधा को C # 5.0 के लिए नामांकित करता हूं। मुझे नहीं पता या परवाह नहीं है कि ग्रूवी वास्तव में क्या है, लेकिन यह किसी भी भाषा में उपयोग करने के लिए पर्याप्त सहज है।
ग्योर्गी एंड्रेसेक

हालाँकि यह अब C # 6 में जोड़ा जा रहा है, हुर्रे।
जेफ मर्काडो

1
सुरक्षित-नेविगेशन पोस्ट किए गए तुच्छ उदाहरण के लिए काम करता है, लेकिन आपको अभी भी टर्नरी ऑपरेटर का उपयोग करने की आवश्यकता है यदि आप फ़ंक्शन कॉल में गैर-शून्य मान का उपयोग करने का इरादा रखते हैं, उदाहरण के लिए Decimal? post = pre == null ? null : SomeMethod( pre );:। यह अच्छा होगा यदि मैं इसे "दशमलव; पद = पूर्व :: SomeMethod (पूर्व);"
दाई

@ दाई: आपके द्वारा चाहा जा सकता है कि मेरी संख्या कितनी है, इसे देखते हुए हमें जो मिला है, मैं उससे काफी खुश हूं।
जॉन स्कीट

36

हमने जोड़ने पर विचार किया। सी # 4. यह कटौती नहीं की; यह एक "अच्छा है" सुविधा है, न कि "गॉट्टा है" सुविधा। हम इसे भाषा के भविष्य के संस्करणों के लिए फिर से विचार करेंगे, लेकिन अगर मैं आप थे तो मैं अपनी सांस रोक नहीं सकता। समय बीतने के साथ इसके और अधिक महत्वपूर्ण होने की संभावना नहीं है। :-)


क्या इसे जोड़ने के निर्णय में एक फीचर प्ले को लागू करने में आसानी होती है? मैं यह पूछता हूं क्योंकि उस ऑपरेटर को लागू करना भाषा के लिए एक बहुत ही सीधे आगे, सरल जोड़ की तरह लगता है। मैं कोई विशेषज्ञ नहीं हूँ (सी # के लिए बड़े प्यार के साथ हाल ही में एक स्नातक), इसलिए कृपया मुझे सही करें!
निक स्ट्रूपट

14
@ निक: ज़रूर, लेसर और पार्सर को लागू करना पाँच मिनट का काम है। फिर आप सामान के बारे में चिंता करना शुरू कर देते हैं जैसे "क्या इंटेलीसेंस इंजन इसे अच्छी तरह से संभालता है?" और "जब आपने टाइप किया है, तो त्रुटि-पुनर्प्राप्ति प्रणाली इससे कैसे निपटती है? लेकिन अभी तक नहीं?" और बस कितने अलग काम करता है "।" C # में वैसे भी, और उनमें से कितने के लायक है? इससे पहले, और अगर आपको यह गलत लगता है, तो त्रुटि संदेश क्या होना चाहिए, और यह परीक्षण कितना आवश्यक है (h: a lot:) की आवश्यकता है और हम इसे कैसे दस्तावेज़ में ले जा रहे हैं और परिवर्तन का संचार करने जा रहे हैं, और ...
एरिक लिपर्ट

3
@nick: आपके प्रश्न का उत्तर देने के लिए - हाँ, कार्यान्वयन लागत एक कारक है, लेकिन एक छोटी सी। हम जिस स्तर पर काम करते हैं, वहां केवल सस्ते या कम खर्चीले फीचर्स ही नहीं हैं। पांच-डॉलर मूल्य के देव कार्य को सही-कोड मामले में पार्सर का काम बनाने के लिए आसानी से डिजाइन, कार्यान्वयन, परीक्षण, प्रलेखन और शिक्षा के हजारों डॉलर के दसियों में बदल सकते हैं।
एरिक लिपर्ट

11
@EricLippert मुझे लगता है कि यह MAJOR में से एक "अच्छा है" होगा, जिसने C # को इतना सफल बना दिया है और यह पूरी तरह से संक्षिप्त और अभिव्यंजक के रूप में कोड बनाने के मिशन को पूरा करेगा!
Konstantin

मैं इसे जोड़ना चाहूंगा, जो मैं वास्तव में चाहता हूं वह एल्विस ऑपरेटर है: stackoverflow.com/questions/2929836/…
क्रिस मैरिसिक

16

यदि आपको एक विशेष प्रकार का शॉर्ट-सर्किट बूलियन लॉजिक मिला है, तो आप ऐसा कर सकते हैं (जावास्क्रिप्ट उदाहरण):

return x && x.y;

यदि xअशक्त है, तो यह मूल्यांकन नहीं करेगा x.y


2
इसके अलावा 0, "" और NaN पर शॉर्ट-सर्किट भी है, इसलिए यह इसके विपरीत नहीं है। यह विपरीत है ||
ऋत

7

इसे सिर्फ एक उत्तर के रूप में जोड़ना सही लगा।

मैं इस कारण का अनुमान लगाता हूं कि C # में ऐसी कोई चीज नहीं है, क्योंकि कॉलेस्सिंग ऑपरेटर (जो केवल संदर्भ प्रकारों के लिए मान्य है) के विपरीत, रिवर्स ऑपरेशन या तो संदर्भ या मूल्य प्रकार (यानी class xसदस्य के साथ ) प्राप्त कर सकता है int y- इसलिए यह दुर्भाग्य से होगा कई स्थितियों में अनुपयोगी।

हालाँकि, मैं यह नहीं कह रहा हूँ कि मैं इसे नहीं देखना चाहूँगा!

उस समस्या का एक संभावित समाधान ऑपरेटर के लिए दायीं ओर एक मूल्य प्रकार की अभिव्यक्ति को एक अशक्त करने के लिए स्वचालित रूप से उठाएगा। लेकिन फिर आपके पास यह मुद्दा है कि x.yवाई कहां एक इंट वास्तव में वापस आ जाएगा int?जो एक दर्द होगा।

एक और, शायद बेहतर, समाधान यह होगा कि ऑपरेटर दाईं ओर के प्रकार के लिए डिफ़ॉल्ट मान (यानी शून्य या शून्य) वापस लौटाए यदि बाईं तरफ की अभिव्यक्ति शून्य है। लेकिन फिर आपके पास अलग-अलग परिदृश्य हैं जहां एक शून्य / नल वास्तव में पढ़ा गया था x.yया क्या यह सुरक्षित-पहुंच ऑपरेटर द्वारा आपूर्ति की गई थी।


जब मैंने पहली बार ओपी के प्रश्न को पढ़ा, तो यह सटीक मुद्दा मेरे सिर में आ गया, लेकिन मैं यह नहीं बता सकता कि इसे कैसे स्पष्ट किया जाए। यह बहुत गंभीर समस्या है। +1
rmeador

यह कोई गंभीर समस्या नहीं है। बस int?डिफ़ॉल्ट रिटर्न मान के रूप में उपयोग करें , और उपयोगकर्ता इसे एक इंट में बदल सकता है यदि वह चाहता है। उदाहरण के लिए, अगर मैं Lookupअपने संदर्भ में डिफ़ॉल्ट मान के साथ -1 के कुछ विधि को कॉल करना चाहूंगा null:foo?.Bar?.Lookup(baz) ?? -1
Qwertie

?. :एक टर्नरी ऑपरेटर होने के बारे में कैसे , जहां दाहिने हाथ की तरफ एक ही प्रकार का होना आवश्यक है, क्योंकि बीच में दिया गया उपयुक्त सदस्य?
सुपरकैट

6

डेल्फी में है: (बल्कि)। ऑपरेटर, जो अशक्त है।

वे एक जोड़ने के बारे में सोच रहे थे? ऑपरेटर सी # 4.0 करने के लिए एक ही है, लेकिन है कि काट ब्लॉक मिल गया।

इस बीच, वहाँ IfNotNull () जो खरोंच की तरह है कि खुजली। यह निश्चित रूप से बड़ा है? या:, लेकिन यह आपको संचालन की एक श्रृंखला की रचना करने देता है जो सदस्यों में से एक के अशक्त होने पर आप पर एक NullReferenceException hork नहीं करेगा।


क्या आप कृपया इस ऑपरेटर का उपयोग करने का एक उदाहरण दे सकते हैं?
मैक्स कैरोल

1
?.एक सी # 6.0 भाषा विशेषता है, और हाँ यह वास्तव में क्या ओपी यहाँ से पूछा है। देर से कभी नहीं ^ ^
T_D

3

हास्केल में, आप >>ऑपरेटर का उपयोग कर सकते हैं :

  • Nothing >> Nothing है Nothing
  • Nothing >> Just 1 है Nothing
  • Just 2 >> Nothing है Nothing
  • Just 2 >> Just 1 है Just 1

3

हास्केल के पास है fmap, जो इस मामले में मुझे लगता है कि इसके बराबर है Data.Maybe.map। हास्केल विशुद्ध रूप से कार्यात्मक है, इसलिए आप जो खोज रहे हैं वह होगा

fmap select_y x

अगर xहै Nothing, इस रिटर्न Nothing। अगर xहै Just object, इस रिटर्न Just (select_y object)। डॉट नोटेशन जितना सुंदर नहीं है, लेकिन यह देखते हुए कि यह एक कार्यात्मक भाषा है, शैली अलग हैं।


2

PowerShell चलो आप एक संदर्भ में गुणों (लेकिन कॉल के तरीकों को नहीं) को संदर्भित करते हैं और यदि अशक्त है तो यह अशक्त हो जाएगा। आप इसे किसी भी गहराई पर कर सकते हैं। मुझे उम्मीद थी कि C # 4 का डायनामिक फ़ीचर इस का समर्थन करेगा लेकिन ऐसा नहीं है।

$x = $null
$result = $x.y  # $result is null

$x = New-Object PSObject
$x | Add-Member NoteProperty y 'test'
$result = $x.y  # $result is 'test'

यह सुंदर नहीं है, लेकिन आप एक विस्तार विधि जोड़ सकते हैं जो आपके द्वारा वर्णित तरीके को कार्य करेगा।

public static TResult SafeGet<T, TResult>(this T obj, Func<T, TResult> selector) {
    if (obj == null) { return default(TResult); }
    else { return selector(obj); }
}

var myClass = new MyClass();
var result = myClass.SafeGet(x=>x.SomeProp);

2
public class ok<T> {
    T s;
    public static implicit operator ok<T>(T s) { return new ok<T> { s = s }; }
    public static implicit operator T(ok<T> _) { return _.s; }

    public static bool operator true(ok<T> _) { return _.s != null; }
    public static bool operator false(ok<T> _) { return _.s == null; }
    public static ok<T> operator &(ok<T> x, ok<T> y) { return y; }
}

मुझे अक्सर तार के लिए इस तर्क की आवश्यकता होती है:

using ok = ok<string>;

...

string bob = null;
string joe = "joe";

string name = (ok)bob && bob.ToUpper();   // name == null, no error thrown
string boss = (ok)joe && joe.ToUpper();   // boss == "JOE"

1

सदस्यों के लिए सभी सही डिफ़ॉल्ट मानों के साथ कहीं न कहीं अपनी कक्षा का एक स्थिर उदाहरण बनाएं।

उदाहरण के लिए:

z = new Thingy { y=null };

फिर तुम्हारे बजाय

return x != null ? x.y : null;

तुम लिख सकते हो

return (x ?? z).y;

मैं कभी-कभी उस तकनीक का उपयोग करता हूं (उदाहरण के लिए (x ?? "") .TStString ()) लेकिन यह केवल कुछ डेटा प्रकारों जैसे POD और स्ट्रिंग्स पर ही व्यावहारिक है।
1922 को क्वर्टी

1

इसे C # vNext (रोज़लिन संचालित सी #, विजुअल स्टूडियो 2014 के साथ रिलीज़) में जोड़ा जा रहा है।

इसे नल प्रसार कहा जाता है और इसे पूर्ण के रूप में यहां सूचीबद्ध किया गया है। https://roslyn.codeplex.com/wikipage?title=Language%20Feature%20Status

इसे यहाँ भी पूरा सूचीबद्ध किया गया है: https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3990187-add-operator-to-c


1

तथाकथित "नल-सशर्त ऑपरेटर" को C # 6.0 और विजुअल बेसिक 14.
में पेश किया गया है । कई स्थितियों में इसे नल-कोलेसिंग ऑपरेटर के सटीक विपरीत के रूप में इस्तेमाल किया जा सकता है:

int? length = customers?.Length; // null if customers is null   
Customer first = customers?[0];  // null if customers is null  
int? count = customers?[0]?.Orders?.Count();  // null if customers, the first customer, or Orders is null

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators

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