2009-03-11 9 views
64

मैं एक परियोजना मैं मैं कहाँ कई, कई स्थानों में निम्नलिखित के लिए जाँच कर रहा हूँ लगता है पर काम कर रहा हूँ में करने के लिए:Nullable प्रकार: सबसे अच्छा तरीका है अशक्त के लिए जाँच या शून्य C#

एक curiousity के रूप में
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); 
} 

वहाँ एक बेहतर तरीका है:

मैं एक सहायक विधि है जो है जोड़ दिया है?

उत्तर

122

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

अद्यतन 1:

तुम भी तरह एक विस्तार विधि निर्धारित कर सकते हैं:

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

और इस तरह इसका इस्तेमाल:

if(item.IsNullOrValue(0)){} // लेकिन आपको इससे बहुत कुछ नहीं मिलता

+1

सौंदर्य की बात। – Patrick

+3

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

+2

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

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

प्रतिबिंब * धीमा * है, इस तरह के समाधानों से सावधान रहें।मैं प्रतिबिंब पर ऑब्जेक्ट नहीं करता हूं, लेकिन मैं इसे इस तरह के "सरल" फ़ंक्शन में उम्मीद नहीं करता और यह मुझे गार्ड से पकड़ लेगा। –

+0

क्या यह वास्तव में शून्य की जांच करता है? – nailitdown

+0

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

2

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

आप तार के साथ काम कर रहे हैं का उपयोग करता है, तो (String.IsNullOrEmpty (myStr))

2

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

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

+0

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

+0

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

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

आपका समाधान एक प्रॉपर्टी के लिए काम करता है, मुझे यह निर्दिष्ट करना चाहिए कि मेरे पास शून्य/शून्य – nailitdown

35

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

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 यह एक संदर्भ प्रकार है, valuenull (default(T)) के साथ तुलना में किया जाएगा, अन्यथा, अगर T एक value type है, की दोहरी मान लीजिए, default(t) है 0 डी, बूल के लिए false है, char के लिए '\0' है और इसलिए ...

1

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

अच्छा, यदि आप वास्तव में बेहतर तरीके से खोज रहे हैं, तो आप शायद दर के शीर्ष पर अमूर्तता की एक और परत जोड़ सकते हैं। वैसे यहां कुछ ऐसा है जो मैं अभी नलबल डिजाइन पैटर्न का उपयोग कर आया हूं।

 
using System; 
using System.Collections.Generic; 

namespace NullObjectPatternTest 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      var items = new List 
          { 
           new Item(RateFactory.Create(20)), 
           new Item(RateFactory.Create(null)) 
          }; 

      PrintPricesForItems(items); 
     } 

     private static void PrintPricesForItems(IEnumerable items) 
     { 
      foreach (var item in items) 
       Console.WriteLine("Item Price: {0:C}", item.GetPrice()); 
     } 
    } 

    public abstract class ItemBase 
    { 
     public abstract Rate Rate { get; } 
     public int GetPrice() 
     { 
      // There is NO need to check if Rate == 0 or Rate == null 
      return 1 * Rate.Value; 
     } 
    } 

    public class Item : ItemBase 
    { 
     private readonly Rate _Rate; 
     public override Rate Rate { get { return _Rate; } } 
     public Item(Rate rate) { _Rate = rate; } 
    } 

    public sealed class RateFactory 
    { 
     public static Rate Create(int? rateValue) 
     { 
      if (!rateValue || rateValue == 0) 
       return new NullRate(); 
      return new Rate(rateValue); 
     } 
    } 

    public class Rate 
    { 
     public int Value { get; set; } 
     public virtual bool HasValue { get { return (Value > 0); } } 
     public Rate(int value) { Value = value; } 
    } 

    public class NullRate : Rate 
    { 
     public override bool HasValue { get { return false; } } 
     public NullRate() : base(0) { } 
    } 
} 
+1

की जांच करने के लिए एक ही आइटम के कई गुण हैं, मुझे लगता है कि आप सही हैं कि कुछ पहले चरण में शून्य मानों को समाप्त करना एक तरीका होगा – nailitdown

+0

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

0

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

String.IsNullOrEmpty(str) 

बजाय:

str==null || str=="" 
+1

प्रश्न "0" के खिलाफ एक खाली स्ट्रिंग नहीं है। – Sung

16

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

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)); 
} 

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

उदाहरण:

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

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

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

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

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

यह समाधान

  • को अतिरिक्त विधि की आवश्यकता नहीं है,
  • अन्य सभी विकल्पों की तुलना में तेज़ है, GetValueOrDefault is a single field read operation ¹ और
  • ((item.Rate ?? 0) == 0) से आसान पढ़ता है (हालांकि यह स्वाद का मामला हो सकता है)।

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