अशक्त प्रकार: n # में शून्य या शून्य की जांच करने का बेहतर तरीका


85

मैं एक परियोजना पर काम कर रहा हूँ जहाँ मुझे कई, कई स्थानों पर निम्नलिखित के लिए जाँच कर रहा हूँ:

if(item.Rate == 0 || item.Rate == null) { }

किसी भी चीज़ से अधिक उत्सुकता के रूप में, दोनों मामलों की जांच करने का सबसे अच्छा तरीका क्या है?

मैंने एक सहायक विधि जोड़ी है जो है:

public static bool nz(object obj)
{
    var parsedInt = 0;
    var parsed = int.TryParse(obj.ToString(), out parsedInt);
    return IsNull(obj) || (parsed && parsedInt == 0);
}

क्या कोई बेहतर तरीका है?

जवाबों:


161

मुझे पसंद है if ((item.Rate ?? 0) == 0) { }

अपडेट 1:

आप एक एक्सटेंशन विधि भी परिभाषित कर सकते हैं जैसे:

public static bool IsNullOrValue(this double? value, double valueToCheck)
{
    return (value??valueToCheck) == valueToCheck;
}

और इसे इस तरह से उपयोग करें:

if(item.IsNullOrValue(0)){} // लेकिन आपको इससे ज्यादा नहीं मिलता है


3
धन्यवाद - बहुत रसीला! मैं पठनीयता से चिंतित था, लेकिन इस निष्कर्ष पर पहुंचा कि यह पूरी तरह से पठनीय होगा क्या मैं वास्तव में समझ गया था ?? ऑपरेटर।
कीलितडाउन

2
आपको एक्सटेंशन विधि का उपयोग करना चाहिए; जब यह लिखने के क्षण में पठनीय होता है, तो इस छोटे कोड की डली को विचार के एक अंश की आवश्यकता होती है, जिसका अर्थ है कि यदि आप कोड को पढ़ने की कोशिश करते हैं और इसका उपयोग करते हैं - तो आप अपनी मुख्य समस्या से विचलित हो जाते हैं।
विन्यासकर्ता

11
@nailitdown: वास्तव में नहीं, आपको बस Nullable <T> के लिए एक विस्तार विधि की आवश्यकता है। दोगुना? Nullable <double> के लिए एक उपनाम है। Struct: सार्वजनिक स्थैतिक bool IsNullOrValue <टी> (यह Nullable <टी>, टी valueToCheck) जहां टी: अपने हस्ताक्षर की तरह दिखाई देगा
यहोशू शैनन

3
@nailitdown: (भाग II) आपका रिटर्न स्टेटमेंट फिर रिटर्न (वैल्यू ?? डिफॉल्ट (टी)) की तरह दिखेगा। इक्वल्स (valueToCheck);
जोशुआ शैनन

2
यदि आप इसे "इसनुल्ऑर (0)" के रूप में संक्षिप्त करते हैं, तो यह स्वाभाविक रूप से "शून्य या शून्य" के रूप में पढ़ा जाएगा
क्रिसफॉक्स

41

जेनरिक का उपयोग करना:

static bool IsNullOrDefault<T>(T value)
{
    return object.Equals(value, default(T));
}

//...
double d = 0;
IsNullOrDefault(d); // true
MyClass c = null;
IsNullOrDefault(c); // true

यदि Tयह एक संदर्भ प्रकार है , valueतो इसकी तुलना null( default(T)) के साथ की जाएगी , अन्यथा, यदि Tकोई है value type, तो आइए default(t)दोहराते हैं, 0d है, बूल के लिए है false, चार के लिए है '\0'और इसी तरह ...


1
विस्तार विधि:public static bool IsNullOrValue<T>(this T? value, T valueToCheck) where T : struct { return (value ?? default(T)).Equals(valueToCheck); }
बेहज़ाद अब्राहिमी

39

हालाँकि मुझे स्वीकार किए गए उत्तर काफी पसंद हैं, मुझे लगता है कि, पूर्णता के लिए, इस विकल्प का भी उल्लेख किया जाना चाहिए:

if (item.Rate.GetValueOrDefault() == 0) { }

यह समाधान

  • एक अतिरिक्त विधि की आवश्यकता नहीं है,
  • अन्य सभी विकल्पों की तुलना में तेज़ है, क्योंकि GetValueOrDefault एक एकल फ़ील्ड रीड ऑपरेशन other और है
  • की तुलना में आसान पढ़ता है ((item.Rate ?? 0) == 0)(यह स्वाद का मामला हो सकता है, हालांकि)।

Influence इससे आपके निर्णय पर कोई प्रभाव नहीं पड़ना चाहिए, हालाँकि, इस प्रकार के सूक्ष्म अनुकूलन से कोई फर्क नहीं पड़ता है।


19

यह वास्तव में फ्रेडी रियोस के केवल जेनरिक का उपयोग करके स्वीकृत उत्तर का विस्तार है।

public static bool IsNullOrDefault<T>(this Nullable<T> value) where T : struct
{
    return default(T).Equals( value.GetValueOrDefault() );
}

public static bool IsValue<T>(this Nullable<T> value, T valueToCheck) where T : struct
{
    return valueToCheck.Equals((value ?? valueToCheck));
}

ध्यान दें कि हमें शून्य के लिए डिफ़ॉल्ट (T) की जाँच करने की आवश्यकता नहीं है क्योंकि हम या तो मूल्य प्रकारों या संरचनाओं के साथ काम कर रहे हैं! इसका मतलब यह भी है कि हम सुरक्षित रूप से मान सकते हैं कि टी वैल्यूचेक शून्य नहीं होगा; यहाँ याद है कि टी? आशुलिपि अशक्त है <T> तो Nullable <T> के विस्तार को जोड़कर हम विधि को अंतर में प्राप्त करते हैं ?, डबल ?, बूल? आदि।

उदाहरण:

double? x = null;
x.IsNullOrDefault(); //true

int? y = 3;
y.IsNullOrDefault(); //false

bool? z = false;
z.IsNullOrDefault(); //true

2

मैं का उपयोग करने के साथ सहमत हूँ ?? ऑपरेटर।

यदि आप स्ट्रिंग्स के साथ काम कर रहे हैं तो (String.IsNullOrEmpty (myStr))


2

क्या कोई बेहतर तरीका है?

ठीक है, अगर आप वास्तव में बेहतर तरीके की तलाश कर रहे हैं, तो आप शायद दर के शीर्ष पर अमूर्त की एक और परत जोड़ सकते हैं। यहाँ कुछ है जो मैं अभी Nullable Design Pattern का उपयोग करके आया हूँ।

सिस्टम का उपयोग कर;
System.Collections.Generic का उपयोग कर;

नामस्थान NullObjectPatternTest
{
    सार्वजनिक वर्ग कार्यक्रम
    {
        सार्वजनिक स्थैतिक शून्य main (String [] args)
        {
            var आइटम = नई सूची
                            {
                                नया आइटम (RateFactory.Create (20)),
                                नया आइटम (RateFactory.Create (अशक्त))
                            };

            PrintPricesForItems (आइटम);
        }

        निजी स्थिर शून्य PrintPricesForItems (IEnumerable आइटम)
        {
            foreach (आइटम में var आइटम)
                Console.WriteLine ("आइटम मूल्य: {0: C}", item.GetPrice ());
        }
    }

    सार्वजनिक सार वर्ग
    {
        सार्वजनिक सार दर दर {मिलता है; }
        सार्वजनिक int GetPrice ()
        {
            // दर == 0 या दर == अशक्त होने पर जाँचने की कोई आवश्यकता नहीं है
            वापसी 1 * दर।
        }
    }

    सार्वजनिक वर्ग आइटम: ItemBase
    {
        निजी आसानी से रेट _Rate;
        सार्वजनिक ओवरराइड दर दर {प्राप्त {वापसी _Rate; }}
        सार्वजनिक मद (दर दर) {_Rate = दर; }
    }

    पब्लिक सीलबंद क्लास रेटफैक्टरी
    {
        सार्वजनिक स्थैतिक दर बनाएँ (int? rateValue)
        {
            अगर (रेटवैल्यू || रेटवैल्यू == 0) 
                नया NullRate () लौटाएं;
            नई दर लौटाएं (रेटवैल्यू);
        }
    }

    सार्वजनिक वर्ग की दर
    {
        सार्वजनिक int मान {प्राप्त करें; सेट; }
        सार्वजनिक आभासी बूल HasValue {प्राप्त {वापसी (मान> 0); }}
        सार्वजनिक दर (अंतर मूल्य) {मूल्य = मूल्य; }
    }

    सार्वजनिक वर्ग NullRate: दर
    {
        सार्वजनिक ओवरब्रिज बूल हैसवेल्यू {प्राप्त {वापस झूठी; }}
        सार्वजनिक अशक्त (): आधार (0) {}
    }
}

1
मुझे लगता है कि आप सही हैं कि कुछ पहले के स्तर पर अशक्त मूल्यों को समाप्त करने का रास्ता तय करना होगा
नेलटाउनडाउन

बिल्कुल नहीं। एक अवधारणा है जिसे "रिफैक्टिंग" कहा जाता है। आप एक बेहतर पैटर्न या बेहतर संरचना की ओर अपने कोड को रिफ्लेक्टर कर सकते हैं। आप बाद के चरणों में हमेशा अशक्त मूल्यों को समाप्त कर सकते हैं ।
डांस

2

आप कोड नमूना विफल हो जाएगा। यदि obj अशक्त है, तो obj.ToString () एक अशक्त संदर्भ अपवाद के परिणामस्वरूप होगा। मैं इस प्रक्रिया को छोटा कर देता हूं और अपने सहायक कार्य की शुरुआत में एक अशक्त ओब्ज के लिए जांच करता हूं। अपने वास्तविक प्रश्न के अनुसार, आप शून्य या शून्य के लिए किस प्रकार की जाँच कर रहे हैं? स्ट्रिंग पर एक महान IsNullOrEmpty फ़ंक्शन है, मुझे लगता है कि यह int पर एक IsNullOrZero विधि को लागू करने के लिए विस्तार विधियों का एक बड़ा उपयोग होगा? प्रकार।

संपादित करें: याद रखें, '?' इनुल्यबल टाइप के लिए बस कंपाइलर शुगर है, इसलिए आप शायद एक इन्युलेबल को परम के रूप में ले सकते हैं और फिर jsut इसे null (parm == null) से तुलना करते हैं और यदि शून्य की तुलना शून्य नहीं है।


उस बग को पकड़ने के लिए चीयर्स - इस परियोजना में मुझे int के खिलाफ जांच करने की आवश्यकता है ?, डबल ?, दशमलव ?, इत्यादि जिसके कारण मैं "ऑब्जेक्ट" का उपयोग कर रहा हूं
nititdown

याद करो '?' केवल अतुलनीय <T> प्रकार के लिए कंपाइलर शुगर है, इसलिए आप संभवतः एक इन्युलेबल <T> ले सकते हैं क्योंकि parm और फिर jsut इसे null (parm == null) से तुलना करता है और यदि शून्य शून्य की तुलना में नहीं है।
वाल्डेन लीवरिच

0
public static bool nz(object obj)
{
    return obj == null || obj.Equals(Activator.CreateInstance(obj.GetType()));
}

1
प्रतिबिंब धीमा है , इस तरह के समाधान के साथ सावधान रहें। मुझे प्रतिबिंब से कोई आपत्ति नहीं है, लेकिन मैं इस तरह से "सरल" फ़ंक्शन में इसकी उम्मीद नहीं करूंगा और यह मुझे बंद गार्ड को पकड़ लेगा।
वाल्डेन लीवरिच

क्या यह वास्तव में शून्य की जांच करता है?
कीलितडाउन

दरअसल नहीं। Activator.CreateInstance (obj.GetType ()) अशक्त प्रकारों के लिए शून्य वापस आ जाएगी, मुझे विश्वास है।
विन्यासकर्ता

@configurator: जब अशक्त प्रकारों को बॉक्सिंग किया जाता है, तो उन्हें अंतर्निहित संरचना के रूप में बॉक्सिंग किया जाता है, अर्थात, इससे अशक्त-मान अशक्त नहीं बनेंगे, लेकिन एक डिफ़ॉल्ट-मूल्यवान गैर-अशक्त संरचना।
Eamon Nerbonne

0
class Item{  
 bool IsNullOrZero{ get{return ((this.Rate ?? 0) == 0);}}
}

आपका समाधान एक संपत्ति के लिए काम करता है, मुझे निर्दिष्ट करना चाहिए कि मेरे पास शून्य / शून्य के लिए जांच करने के लिए एक ही आइटम के कई गुण हैं
नेलटाइटड

0

तार के लिए मत भूलना, आप हमेशा उपयोग कर सकते हैं:

String.IsNullOrEmpty(str)

के बजाय:

str==null || str==""

1
प्रश्न "0" के खिलाफ तुलना करता है न कि एक रिक्त स्ट्रिंग के रूप में।
डांस

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