“X null” और “x == null” में क्या अंतर है?


277

C # 7 में हम उपयोग कर सकते हैं

if (x is null) return;

के बजाय

if (x == null) return;

क्या पुराने तरीके से नए तरीके (पूर्व उदाहरण) का उपयोग करने के कोई फायदे हैं?

क्या शब्दार्थ कोई भिन्न हैं?

क्या सिर्फ स्वाद की बात है? यदि नहीं, तो मुझे एक का उपयोग कब करना चाहिए?

संदर्भ: C # 7.0 में नया क्या है


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

2
@SimonPrice वह C #: C # 6. के वर्तमान संस्करण के बारे में है। यह प्रश्न C # 7 के बारे में है, जिसमें पैटर्न मिलान है
पैट्रिक हॉफमैन

@bigown आप किस तरह के विवरण की तलाश में हैं?
पैट्रिक हॉफमैन

@PatrickHofman ने svick का जवाब दिया, उदाहरण के लिए
Maniero

जवाबों:


231

अद्यतन: रोसलिन कंपाइलर को दो ऑपरेटरों के व्यवहार को एक ही बनाने के लिए अद्यतन किया गया है जब कोई अतिभारित समानता ऑपरेटर नहीं है । कृपया वर्तमान संकलक परिणामों में कोड देखें ( M1और M2कोड में) जो दिखाता है कि जब कोई अतिभारित समानता तुलना नहीं होती है तो क्या होता है। वे दोनों अब बेहतर प्रदर्शन करने वाला ==व्यवहार रखते हैं। यदि कोई अतिभारित समानता है, तो कोड अभी भी अलग है

नीचे दिए गए विश्लेषण के रोसलिन संकलक के पुराने संस्करणों के लिए देखें।


क्योंकि nullहम C # 6 के साथ जो उपयोग करते हैं, उसमें कोई अंतर नहीं है। हालांकि, जब आप nullकिसी अन्य स्थिरांक में बदलते हैं तो चीजें दिलचस्प हो जाती हैं ।

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

Test(1);

public void Test(object o)
{
    if (o is 1) Console.WriteLine("a");
    else Console.WriteLine("b");
}

परीक्षण से पैदावार होती है a। यदि आप तुलना करते हैं o == (object)1कि आपने सामान्य रूप से क्या लिखा है, तो यह एक अंतर का नरक बनाता है। isतुलना के दूसरी तरफ प्रकार को ध्यान में रखता है। वह शांत है!

मुझे लगता है कि == nullबनाम is nullस्थिर पैटर्न सिर्फ कुछ ऐसा है जो 'दुर्घटना से बहुत परिचित' है, जहां isऑपरेटर और बराबर ऑपरेटर का सिंटैक्स एक ही परिणाम देता है।


के रूप में svick टिप्पणी की, is nullकॉल System.Object::Equals(object, object)जहां ==कॉलceq

आईएल के लिए is:

IL_0000: ldarg.1              // Load argument 1 onto the stack
IL_0001: ldnull               // Push a null reference on the stack
IL_0002: call bool [mscorlib]System.Object::Equals(object, object) // Call method indicated on the stack with arguments
IL_0007: ret                  // Return from method, possibly with a value

आईएल के लिए ==:

IL_0000: ldarg.1              // Load argument 1 onto the stack
IL_0001: ldnull               // Push a null reference on the stack
IL_0002: ceq                  // Push 1 (of type int32) if value1 equals value2, else push 0
IL_0004: ret                  // Return from method, possibly with a value

जब से हम बात कर रहे हैं null, तब से कोई अंतर नहीं है क्योंकि यह केवल उदाहरणों पर फर्क करता है । यह तब बदल सकता है जब आपने समानता ऑपरेटर को अधिभारित किया हो।


15
@PatrickHofman यह isकॉल की तरह दिखता है object.Equals(x, null), जबकि ==संकलन करता है ceqलेकिन परिणाम वही होना चाहिए, जैसा आपने कहा था।
16

16
हमेशा ध्यान रखें कि ==एक अधिभार ऑपरेटर है। आप इसके साथ कोई भी व्यवहार कर सकते हैं। उदाहरण के लिए, यह अजीब तरह से लागू नहीं होगा== आपको बताएं कि क्या आपका उदाहरण वास्तव में अशक्त है। is nullदूसरी ओर, हमेशा सही अशक्त संदर्भों के लिए सही लौटेगा :) इसके अलावा, यदि आपके पास ReferenceEqualsआपके कोड में है, तो वीएस 2017 लाइट बल्ब बदलने का सुझाव देगा is null, न कि == null(सही तरीके से)।
नवफल

2
@PatrickHofman @ दो null चेक अब एक ही चीज़ के लिए संकलित करते हैं, इसलिए isजब null की जाँच करने के लिए उपयोग किया जाता है तो फ़ंक्शन कॉल का ओवरहेड नहीं होता है। प्रमाण के लिए, टिप्पणियों में @svick द्वारा पोस्ट किया गया लिंक देखें।
आंद्रियासहसिंग

1
@ AndreasBjørnHassingNielsen ने मेरा जवाब अपडेट किया।
पैट्रिक हॉफमैन

2
@ पैट्रिकहोफमैन को आईएल के आसपास दूसरा रास्ता नहीं होना चाहिए? == कॉल System.Object :: बराबर (ऑब्जेक्ट, ऑब्जेक्ट) और null कॉल सीक है
Zbigniew Ledwo19

67

ओवरलोडेड बराबर ऑपरेटर

वास्तव में दोनों तुलनाओं के बीच शब्दार्थ में अंतर होता है जब आप nullएक प्रकार के साथ तुलना कर रहे हैं जिसने ==ऑपरेटर को अधिभारित किया है। foo is nullपरिणाम का निर्धारण करने के लिए प्रत्यक्ष संदर्भ तुलना का उपयोग करेगा, जबकि अगर यह मौजूद है तो foo == nullनिश्चित रूप से अतिभारित ==ऑपरेटर को चलाएगा ।

इस उदाहरण में मैंने ओवरलोडेड ==ऑपरेटर में एक "बग" पेश किया है , जिससे दूसरा तर्क होने पर इसे हमेशा एक अपवाद के रूप में फेंकना पड़ता है null:

void Main()
{
    Foo foo = null;

    if (foo is null) Console.WriteLine("foo is null"); // This condition is met
    if (foo == null) Console.WriteLine("foo == null"); // This will throw an exception
}

public class Foo
{
    public static bool operator ==(Foo foo1, Foo foo2)
    {
        if (object.Equals(foo2, null)) throw new Exception("oops");
        return object.Equals(foo1, foo2);
    }

    // ...
}

प्रत्यक्ष संदर्भ तुलना करने के लिए अनुदेश foo is nullका उपयोग करने के लिए IL कोड ceq:

IL_0003:  ldloc.0     // foo
IL_0004:  ldnull      
IL_0005:  ceq

foo == nullओवरलोड ऑपरेटर को कॉल करने के लिए IL कोड :

IL_0016:  ldloc.0     // foo
IL_0017:  ldnull      
IL_0018:  call        UserQuery+Foo.op_Equality

तो अंतर यह है, कि यदि आप ==उपयोगकर्ता कोड चलाने में जोखिम का उपयोग करते हैं (जो संभवतः अप्रत्याशित व्यवहार या प्रदर्शन की समस्या हो सकती है)।

जेनेरिक पर प्रतिबंध

is nullकंस्ट्रक्शन के उपयोग से टाइप को रेफरेंस टाइप तक सीमित कर दिया जाता है। संकलक यह सुनिश्चित करता है, जिसका अर्थ है कि आप is nullमूल्य प्रकार पर उपयोग नहीं कर सकते हैं । यदि आपके पास एक सामान्य विधि है, तो आप is nullतब तक उपयोग नहीं कर पाएंगे जब तक कि सामान्य प्रकार एक संदर्भ प्रकार होने के लिए विवश न हो।

bool IsNull<T>(T item) => item is null;                  // Compile error: CS0403
bool IsNull<T>(T item) => item == null;                  // Works
bool IsNull<T>(T item) where T : class => item is null;  // Works

इस ओर इशारा करने के लिए डेविड ऑगस्टो विला का धन्यवाद ।


2
इसके अलावा, नोट (x null) के लिए एक वर्ग बाधा की आवश्यकता होती है यदि x एक सामान्य प्रकार है, जबकि (x == null) और ऑब्जेक्ट। ReferenceEquals (x, null) नहीं करते हैं।
डेविड ऑगस्टो विला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.