2015-01-31 9 views
9

मेरी प्रोग्रामिंग परीक्षा के लिए मुझे लिखे गए कोड की रक्षा करना पड़ा। लाइनों में से एक हैं:क्या यह जांचने का क्रम है कि कोई स्ट्रिंग शून्य या खाली है या नहीं?

if(app.Logourl == "" || app.Logourl == null) 

उसने मुझसे पूछा कि शून्य और खाली स्ट्रिंग के बीच कोई अंतर था या नहीं। मैंने उनसे कहा कि अंतर यह था कि null का अर्थ है कि यह किसी भी चीज़ को इंगित नहीं करता है, इसलिए यह तत्काल नहीं है, लेकिन खाली स्ट्रिंग है।

परीक्षा के बाद मैं उसके पास गया और उससे पूछा कि क्या मैं सही था, क्योंकि मैंने उसके चेहरे पर एक मजाकिया रूप देखा। उसने मुझे बताया कि यह सच है कि वे अलग हैं, लेकिन जिस क्रम में मैंने मूल्यों की जांच की वह गलत थी।

अब कुछ दिनों बाद मुझे विश्वास है कि आदेश में कुछ भी गलत नहीं है। क्या मैं सही हूँ?

टी एल; डॉ

if(app.Logourl == "" || app.Logourl == null) 

if(app.Logourl == null || app.Logourl == "") 
+4

इसके बजाय 'स्ट्रिंग.इन्स नलऑरफेक्टी' का उपयोग करें;) –

+1

फरहाद सही है। इसके अलावा, माइक्रो-माइक्रो-ऑप्टिमाइज़ेशन के लिए, जो शर्त आपको लगता है वह सबसे पहले सच होगा, शॉर्ट-सर्किट मूल्यांकन के लिए अधिक मामलों में अंतिम जांच छोड़ दें। –

+1

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

उत्तर

14

यह ठीक तरह से आप यह किया है, क्योंकि System.String कॉल String.Equals, जो null रों की अनुमति देता है के लिए == का अधिभार।

यह सार्वभौमिक नहीं है, तथापि जाता है: यदि आप इसके बजाय == "" का उपयोग करने का स्ट्रिंग लंबाई की जांच करना चाहता था, अपने पहले कोड स्निपेट मुसीबत में होगा:

if(app.Logourl.Length == 0 || app.Logourl == null) // <<== Wrong! 

दूसरा एक ठीक होगा, जबकि:

if(app.Logourl == null || app.Logourl.Length == 0) // <<== Correct 

इस का कारण यह || और && ऑपरेटरों के मूल्यांकन में कम सर्किटिंग है: एक बार वे परिणाम पता (true के लिए ||, के लिए) वे मूल्यांकन बंद कर देते हैं। उपरोक्त दूसरे स्निपेट में, यदि app.Logourlnull है, तो अभिव्यक्ति का दूसरा भाग अनदेखा कर दिया जाएगा, इसलिए app.Logourl.Length एक शून्य संदर्भ अपवाद नहीं फेंक देगा।

नोट: यह सब जगह है, सी # वर्ग पुस्तकालय offers a convenience method for doing this check भर में हो रहा है जैसे चेकों को मान्यता:

if (string.IsNullOrEmpty(app.Logourl)) { 
    ... 
} 
+2

आपके पहले कथन में मैं टिप्पणी जोड़ सकता हूं कि सी # विनिर्देश द्वारा परिभाषित '==' ऑपरेटर के सभी अधिभार, जिसमें नलिकाओं पर उठाए गए ऑपरेटरों समेत, और बीसीएल द्वारा परिभाषित '==' के सभी अतिरिक्त अधिभार, (यानी) फेंक नहीं) एक या दोनों ऑपरेशन 'शून्य' होने के लिए। एक उपयोगकर्ता '==' जो ओवर फेंकता है, का अधिभार पेश कर सकता है, लेकिन मुझे लगता है कि' == 'को लागू करने के तरीके पर "अनुबंध" तोड़ दिया जाएगा। –

1

(आपके मामले में) नहीं, यह कोई बात नहीं के बराबर है।

एक बात हालांकि पता करने के लिए, कि बूलियन ऑपरेटरों && और || शॉर्ट सर्किट, जिसका मतलब है अगर तुम a || b और a है true है, तो b मूल्यांकन नहीं किया जाता है।

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

app.Logourl == null || app.Logourl == "" 

तो app.Logourlnull, तो app.Logourl == "" भी मूल्यांकन किया जाता कभी नहीं रहा है।

आपके मामले में, कोई वास्तविक अंतर नहीं है कि आप एक या दूसरे की जांच करते हैं या नहीं। पहले या दूसरे पहले। यदि वहां जांच अलग थी, तो इससे कोई फर्क नहीं पड़ता।

उदाहरण के लिए

,

app.Logourl == null || app.Logourl.Equals("") 

आप अन्य आदेश किया था, तो आप एक अपवाद है, तो app.Logourlnull है, जब से तुम अशक्त संदर्भों के सदस्य कार्यों कॉल नहीं कर सकते मिलेगा।


हालांकि मैं String.IsNullOrEmpty(app.Logourl) का उपयोग करता हूं, जो मानक lib है।

0

जब मुझे यकीन है कि मेरी वस्तु एक string मैं हमेशा निम्नलिखित पसंद करते है कर रहा हूँ:

if (string.IsNullOrEmpty(yourString)) 
    { 
     // this string is null or empty 
    } 

या इस:

if (string.IsNullOrWhiteSpace(yourString)) 
    { 
     // this string is null or empty (or got only a space) 
    } 
+1

ध्यान दें कि यदि आप * सुनिश्चित नहीं हैं कि यह एक स्ट्रिंग है या नहीं, यानी यदि घोषित प्रकार (संकलन-समय प्रकार) 'ऑब्जेक्ट 'या एक इंटरफ़ेस है जो' स्ट्रिंग 'लागू करता है, तो कह रहा है **' obj == " "** ** संकलन-समय चेतावनी देना चाहिए। यह खतरनाक है क्योंकि यह संदर्भ समानता के लिए जांच करता है। कभी-कभी 'स्ट्रिंग' के एक से अधिक उदाहरण होते हैं जो खाली होते हैं। –

1

यह सिर्फ एक टिप्पणी है।

सामान्य परिस्थितियों में इससे कोई फर्क नहीं पड़ता। लेकिन दुष्प्रभाव हो सकते हैं।

static class Program 
{ 
    static string Logourl 
    { 
     get 
     { 
      Console.WriteLine("getter runs"); 
      return null; 
     } 
    } 

    static void Main() 
    { 
     if (Logourl == "" || Logourl == null) 
     { 
     } 
    } 
} 

इस कार्यक्रम लिखेंगे:

getter runs 
getter runs

आप चेक के आदेश स्वैप करते हैं, तो getter runs केवल एक बार प्रिंट होगा यहाँ जानने के लिए से एक सरल उदाहरण है। यदि आप संपत्ति को return ""; पर बदलते हैं, तो यह विपरीत होगा।

string.IsNullOrEmpry(Logurl) का उपयोग कर हमेशा एक बार संपत्ति को पुनर्प्राप्त कर देगा।

2
private static bool IsNullOrEmpty(string s) 
    { 
     return s == null || s == ""; 

     /* 
     Lets look behind the scenes here: 
     ================================= 
     IL_0000: ldarg.0 => load s on the evaluation stack 
     IL_0001: brfalse.s IL_000f => GoTo label 'IL_000f' if loaded argument is null 

     IL_0003: ldarg.0 => load s on the evaluation stack 
     IL_0004: ldstr "" => load constant string "" to the evaluation stack 
     IL_0009: call bool [mscorlib]System.String::op_Equality(string, string) 
           => Call String.Equality(string,string) with s and "" 
           loaded to the evalutation stack 
           that will pop the two values compare them for equality and load the result. 
           to the evaluation stack.          

     IL_000e: ret => Return to the caller with equlity result on the evauation stack. 

     IL_000f: ldc.i4.1 => Load constant value 1(4 byte which will represent "True") to the evaluation stack 
          and return to the caller.In our flow it's the case when s is null. 
     IL_0010: ret 

     In Summary: 
     =========== 
     1.) IL instructions total code size 17 bytes. 
     2.) Best case scenario execution path => 2 IL instructions. 
     3.) Worst case scenario execution pat => 8 IL instructions. 

     */ 
    } 

    private static bool IsEmptyOrNull(string s) 
    { 
     return s == "" || s == null; 

     /* 
     Lets look behind the scenes here: 
     ================================= 
     IL_0000: ldarg.0 => load s on the evaluation stack 
     IL_0001: ldstr "" => load constant string "" to the evaluation stack 
     IL_0006: call bool [mscorlib]System.String::op_Equality(string, string) 
     IL_000b: brtrue.s IL_0012 

     IL_000d: ldarg.0 => load s on the evaluation stack 
     IL_000e: ldnull => load constant null on the evaluation stack 
     IL_000f: ceq => Pop two loaded values compare and push the result back on the evaluation stack 
     IL_0011: ret 

     IL_0012: ldc.i4.1 => Load constant value 1(4 byte which will represent "True") to the evaluation stack 
          and return to the caller.In our flow it's the case when s is null. 
     IL_0013: ret 

      In Summary: 
     =========== 
     1.) IL instructions total code size 20 bytes. 
     2.) Best case scenario execution path => 6 IL instructions. 
     3.) Worst case scenario execution path => 10 IL instructions. 
    */ 

    } 

निष्कर्ष:

आईएल उत्सर्जित कोड "अगर (app.Logourl ==" "|| app.Logourl == नल)" कि "microptimization" बेहतर प्रदर्शन बुद्धिमान से केवल आंकना:)

संबंधित मुद्दे

 संबंधित मुद्दे