क्यों अक्सर C # में "वेरिएबल! = Null" के बजाय "null! = Variable" दिखाई देता है?


103

सी # में, क्या उस स्थिति के लिए एक्सर्साइज़ की गति में कोई अंतर है जिसमें आप स्थिति बताते हैं?

if (null != variable) ...
if (variable != null) ...

हाल ही में, मैंने पहले वाले को बहुत बार देखा, और जब से मैं दूसरे के लिए इस्तेमाल किया गया, तब से इसने मेरा ध्यान खींचा।

यदि कोई अंतर नहीं है, तो पहले वाले का क्या फायदा है?



कुछ प्रोग्रामिंग लैंग्वेज इफ कंडीशन में वैल्यू इनिशियलाइज़ करने के लिए सपोर्ट करती हैं। ऐसी भाषाओं में यदि हम RValue के साथ LValue की तुलना करना चाहते हैं तो यह शाब्दिक उपयोग करने के लिए अच्छी तरह से बाईं ओर है जैसे कि (1 = i)। इसलिए गलती से अगर हम = = = डालते हैं तो यह संकलक त्रुटि देता है।
जुगल पांचाल

जवाबों:


161

यह C. से C में एक होल्ड-ओवर है, यदि आप या तो एक खराब संकलक का उपयोग करते हैं या चेतावनी बहुत अधिक नहीं है, तो यह बिना किसी चेतावनी के संकलन करेगा (और वास्तव में कानूनी कोड है):

// Probably wrong
if (x = 5)

जब आप वास्तव में मतलब था

if (x == 5)

आप सी में यह करके काम कर सकते हैं:

if (5 == x)

यहां एक टाइपो में अमान्य कोड होगा।

अब, C # में यह सब पिफल्म है। जब तक आप दो बूलियन मान (जो कि दुर्लभ है, IME) की तुलना कर रहे हैं, तब तक आप अधिक पठनीय कोड लिख सकते हैं, क्योंकि "अगर" कथन के साथ शुरू होने के लिए बूलियन अभिव्यक्ति की आवश्यकता होती है, और " x=5" का प्रकार है Int32, नहीं Boolean

मेरा सुझाव है कि यदि आप इसे अपने सहयोगियों के कोड में देखते हैं, तो आप उन्हें आधुनिक भाषाओं के तरीकों से शिक्षित करते हैं, और सुझाव देते हैं कि वे भविष्य में और अधिक प्राकृतिक रूप लिखें।


6
मेरे सहकर्मी मुझे इसके साथ पागल करते हैं, और अगर एक के बाद भी एक बयान के लिए घुंघराले-कोष्ठक चाहते हैं ... (मामले में आप बाद में 'साकार के बिना कुछ' जोड़ते हैं)। F # और Boo (और YAML) पर रोल करें, यदि आपकी भाषा इंडेंटेशन के बिना अपठनीय है, तो इसे भाषा का हिस्सा बनाएं, मैं कहता हूं।
बेंजोल

48
ब्रेसिज़ जोड़ना है उचित, IMO - सी # निश्चित रूप से एक समस्या होने से इसे रोकने के लिए किसी भी प्रयास नहीं है। यह "स्थिर == चर" समस्या के लिए बहुत अलग है।
जॉन स्कीट

6
a अगर (यह! = उस) {PerformAsSuch (); } वास्तव में काफी स्वस्थ है। "बाद में जोड़ने" का तर्क मेरे लिए नाजुक के रूप में के रूप में नाजुक के रूप में / नहीं
स्पॉटिंग

3
@jpinto: मुझे वास्तव में यकीन नहीं है कि आप यहाँ क्या कहना चाह रहे हैं - कि आप सिंगल स्टेटमेंट्स के आसपास ब्रेसिज़ पसंद करते हैं, या आप नहीं? प्रश्न में इस और चर व्यवसाय के बीच का अंतर यह है कि C # में एक टाइपो वाला कोड अमान्य कोड है इसलिए कंपाइलर इसे रोक देगा। एक ही नहीं है में ब्रेसिज़ डाल नहीं के लिए सच।
जॉन स्कीट

3
@Benjol हमेशा एक खाली else { }क्लॉज की आपूर्ति करना न भूलें , अगर किसी को बाद में वहां कुछ जोड़ने की जरूरत होती है और वह elseखुद कीवर्ड लिखना भूल जाता है । (मजाक)
जेपी स्टिग नीलसन

12

पहले अशक्त उपयोग करने का एक अच्छा कारण है: if(null == myDuck)

यदि आपका ऑपरेटर ऑपरेटर को class Duckओवरराइड करता ==है, तो if(myDuck == null)एक अनंत लूप में जा सकता है।

nullपहले का उपयोग करना एक डिफ़ॉल्ट समानता तुलनित्र का उपयोग करता है और वास्तव में वही करता है जो आप चाहते थे।

(मुझे लगता है कि आपको उस तरह से लिखे गए कोड को पढ़ने की आदत है - मुझे अभी उस परिवर्तन का अनुभव नहीं हुआ है)।

यहाँ एक उदाहरण है:

public class myDuck
{
    public int quacks;
    static override bool operator ==(myDuck a, myDuck b)
    {
        // these will overflow the stack - because the a==null reenters this function from the top again
        if (a == null && b == null)
            return true;
        if (a == null || b == null)
            return false;

        // these wont loop
        if (null == a && null == b)
            return true;
        if (null == a || null == b)
            return false;
        return a.quacks == b.quacks; // this goes to the integer comparison
    }
}

11
ये गलत है। Downvoted। बस ==ऑपरेटर पर माउस को इंगित करें और इसे वहां आराम करें, और आप देखेंगे कि उपयोगकर्ता-परिभाषित अधिभार दोनों मामलों में उपयोग किया जाता है। बेशक, यह एक सूक्ष्म अंतर बना सकता है यदि आप aपहले जांच करते हैं bऔर फिर aदाएं ऑपरेंड से बाएं ऑपरेंड तक की स्थिति को स्वैप करते हैं । लेकिन आप bपहले भी जांच कर सकते हैं a, और फिर b == nullएक होगा जो उलटा क्रम होगा। यह सब ऑपरेटर को स्वयं कॉल करने के लिए भ्रमित कर रहा है। इसके बजाय, objectवांछित अधिभार प्राप्त करने के लिए या तो ऑपरेंड (या दोनों) कास्ट करें । जैसा if ((object)a == null)या if (a == (object)null)
जेपी स्टिग नीलसन

10

जैसा कि पहले से ही उल्लेख किया गया है कि हर कोई सी भाषा से अधिक या कम आता है, जहां आप गलत कोड प्राप्त कर सकते हैं यदि आप गलती से दूसरे समान चिह्न को भूल जाते हैं। लेकिन एक और कारण है जो C #: Readability से भी मेल खाता है।

बस यह सरल उदाहरण लें:

if(someVariableThatShouldBeChecked != null
   && anotherOne != null
   && justAnotherCheckThatIsNeededForTestingNullity != null
   && allTheseChecksAreReallyBoring != null
   && thereSeemsToBeADesignFlawIfSoManyChecksAreNeeded != null)
{
    // ToDo: Everything is checked, do something...
}

यदि आप शुरुआत में सभी अशक्त शब्दों की अदला-बदली करेंगे तो आप सभी जाँचों को आसानी से जान सकते हैं:

if(null != someVariableThatShouldBeChecked
   && null != anotherOne
   && null != justAnotherCheckThatIsNeededForTestingNullity
   && null != allTheseChecksAreReallyBoring
   && null != thereSeemsToBeADesignFlawIfSoManyChecksAreNeeded)
{
    // ToDo: Everything is checked, do something...
}

तो यह उदाहरण शायद एक बुरा उदाहरण है (कोडिंग दिशानिर्देशों का संदर्भ) लेकिन एक पूर्ण कोड फ़ाइल पर त्वरित स्क्रॉल करने के बारे में अभी सोचें। बस पैटर्न देखकर

if(null ...

आप तुरंत जानते हैं कि आगे क्या हो रहा है।

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


9

मुझे लगता है कि यह एक सी प्रोग्रामर है जिसने भाषाओं को बदल दिया है।

C में, आप निम्नलिखित लिख सकते हैं:

int i = 0;
if (i = 1)
{
    ...
}

वहाँ एक समान चिह्न के उपयोग पर ध्यान दें, जिसका अर्थ है कि कोड 1 से चर i को असाइन करेगा, फिर 1 (असाइनमेंट एक अभिव्यक्ति है) लौटें, और 1 का उपयोग अगर-स्टेटमेंट में करें, जिसे सही के रूप में संभाला जाएगा। दूसरे शब्दों में, उपरोक्त एक बग है।

C # में, यह संभव नहीं है। वास्तव में दोनों में कोई अंतर नहीं है।


1
"सी # में, यह संभव नहीं है" कंपाइलर शिकायत के बिना, जैसा कि अगर कथन में बूलियन अभिव्यक्ति की आवश्यकता होती है, और जो प्रदान किया जाता है वह टाइप इंट का है।
रॉबर्ट हार्वे

4

पहले के समय में, लोग 'को भूल जाते थे!' (या समानता के लिए अतिरिक्त '=', जो स्पॉट करना अधिक कठिन है) और तुलना के बजाय एक असाइनमेंट करें। नल को सामने रखना बग के लिए संभावना को समाप्त कर देता है, क्योंकि नल एक एल-वैल्यू नहीं है (IE इसे सौंपा नहीं जा सकता है)।

अधिकांश आधुनिक संकलक एक चेतावनी देते हैं जब आप आजकल एक सशर्त में असाइनमेंट करते हैं, और सी # वास्तव में एक त्रुटि देता है। ज्यादातर लोग बस var == अशक्त योजना से चिपके रहते हैं क्योंकि कुछ लोगों के लिए पढ़ना आसान होता है।


सभी C # संकलक (ध्यान दें कि यह एक C # प्रश्न है) एक "यदि" कथन संकलित करने में विफल होना चाहिए, जहां अभिव्यक्ति एक बूलियन नहीं है ...
जॉन स्कीट

4

इस अधिवेशन का अनुसरण करने में मुझे कोई फायदा नहीं दिख रहा है। सी में, जहां बूलियन प्रकार मौजूद नहीं है, यह लिखना उपयोगी है

if( 5 == variable)

बजाय

if (variable == 5)

क्योंकि यदि आप एक ईगल चिन्ह को भूल जाते हैं, तो आप समाप्त हो जाते हैं

if (variable = 5)

जो 5 से चर के लिए असाइन करता है और हमेशा सच का मूल्यांकन करता है। लेकिन जावा में, एक बूलियन एक बूलियन है। और! = के साथ, कोई कारण नहीं है।

एक अच्छी सलाह, हालांकि, लिखना है

if (CONSTANT.equals(myString))

बजाय

if (myString.equals(CONSTANT))

क्योंकि यह NullPointerException से बचने में मदद करता है।

मेरी सलाह होगी कि आप नियम का औचित्य पूछें। यदि कोई नहीं है, तो इसका पालन क्यों करें? यह पठनीयता में मदद नहीं करता है


0

मेरे लिए यह हमेशा रहा है कि आप किस शैली को पसंद करते हैं

@Shy - फिर अगर आप ऑपरेटरों को भ्रमित करते हैं तो आपको एक संकलन त्रुटि प्राप्त करनी चाहिए या आप बग के साथ कोड चला रहे होंगे - एक बग जो वापस आकर आपको बाद में सड़क से नीचे काट देगा क्योंकि यह अप्रत्याशित व्यवहार उत्पन्न करता है।


मुझे नहीं लगता कि मैं कभी भी पसंद करते हैं "निरंतर == चर" प्रपत्र किसी के बारे में सुना है अन्य सुरक्षा कारणों से, जो पहले से ही सी # से निपटा रहे हैं के लिए की तुलना में।
जॉन स्कीट

मैं अपने आप को "चर == निरंतर" पसंद करता हूं, लेकिन मैंने देखा है कि प्रोग्रामर उल्टे को अपनाते हैं क्योंकि उन्हें लगता है कि यह उनके लिए अधिक स्वाभाविक है।
TheCodeJunkie

1
क्या वे सभी लोग उनके पीछे सी ब्रेनवॉशिंग के वर्षों के साथ थे, या यह एक वास्तविक विकल्प था?
जॉन स्कीट

0

जैसा कि कई ने कहा, यह ज्यादातर पुराने सी कोड में है, इसका उपयोग संकलन त्रुटि को पहचानने के लिए किया गया था, क्योंकि कंपाइलर ने इसे कानूनी रूप से स्वीकार किया था

नई प्रोग्रामिंग लैंग्वेज जैसे जावा, गो, इस तरह की संकलन त्रुटियों को पकड़ने के लिए पर्याप्त स्मार्ट हैं

किसी को कोड में "null! = Variable" जैसी स्थितियों का उपयोग नहीं करना चाहिए क्योंकि यह बहुत ही अपठनीय है


-4

एक और बात ... यदि आप किसी वेरिएबल की निरंतरता (पूर्व के लिए पूर्णांक या स्ट्रिंग) से तुलना कर रहे हैं, तो निरंतर को बाईं ओर रखना अच्छा अभ्यास है क्योंकि आप कभी भी NullPointerException में नहीं चलेंगे:

int i;
if(i==1){        // Exception raised: i is not initialized. (C/C++)
  doThis();
}

जहाँ तक

int i;
if(1==i){        // OK, but the condition is not met.
  doThis();
}

अब, चूंकि डिफ़ॉल्ट C # सभी चर को अस्थिर करता है, इसलिए आपको उस भाषा में यह समस्या नहीं होनी चाहिए।


1
मुझे यकीन नहीं है कि आप कोड के पहले बिट के लिए किस कंपाइलर का उपयोग कर रहे हैं, लेकिन यह संकलन (आमतौर पर एक चेतावनी के साथ) होना चाहिए। I का मान अपरिभाषित है, लेकिन इसका कुछ मान है।
डॉल्फिन

बेशक दोनों कोड संकलन करेंगे! ठीक यही समस्या है। पहले कोड को चलाने की कोशिश करें और आप समझ जाएंगे कि "
एक्ससेप्शन

यह भी दोनों के बीच अंतर नहीं है। क्या आप विस्तार कर सकते हैं?
mfazekas

जब तक आप C / C ++ में int * i घोषित नहीं करते हैं, तब तक कोई अपवाद नहीं है, और उस स्थिति में भी यह पॉइंटर्स की तुलना करेगा और कोई अपवाद नहीं फेंकेगा ... जैसे Dolphin ने कहा कि मान अपरिभाषित है, लेकिन यह कोई अपवाद उत्पन्न नहीं करेगा।
2726

कोई अपवाद नहीं है, iमान लें कि उचित आरंभीकरण के बिना एक यादृच्छिक मूल्य है। अभिव्यक्ति पूरी तरह से c / c ++
Raffaello
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.