2009-03-11 5 views
64

Ich bin an einem Projekt arbeiten, wo ich finde ich bin in vielen, vielen Orten für die folgende Prüfung:Nullable-Typen: beste Weg für null oder null in C# überprüfen

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

mehr als curiousity Was ist der beste Weg, um nach beiden Fällen zu suchen?

Ich habe eine Hilfsmethode gegeben, das ist:

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

Gibt es einen besseren Weg?

Antwort

122

Ich mag if ((item.Rate ?? 0) == 0) { }

Update 1:

Sie auch eine Erweiterungsmethode wie definieren könnte:

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

Und es wie folgt verwenden:

if(item.IsNullOrValue(0)){} // aber Sie erhalten nicht viel davon

+1

Sache der Schönheit. – Patrick

+3

danke - sehr prägnant! Ich war mit der Lesbarkeit beschäftigt, kam aber zu dem Schluss, dass es perfekt lesbar wäre, hätte ich das tatsächlich verstanden? Operator. – nailitdown

+2

Sie sollten die Erweiterungsmethode verwenden; Während es im Moment des Schreibens lesbar ist, benötigen diese kleinen Code-Nuggets nur einen Bruchteil des Gedankens, was bedeutet, dass Sie von Ihrem Hauptproblem abgelenkt werden, wenn Sie versuchen, Code zu lesen. – configurator

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

Reflexion ist * langsam *, seien Sie vorsichtig mit solchen Lösungen.Ich widerspreche nicht der Reflexion, aber ich würde es nicht in einer "einfachen" Funktion wie dieser erwarten und es würde mich überraschen. –

+0

prüft dies tatsächlich auf Null? – nailitdown

+0

Eigentlich nein. Activator.CreateInstance (obj.GetType()) wird Null für Nullable-Typen zurückgeben, glaube ich. – configurator

2

Ich stimme der Verwendung der? Operator.

Wenn Sie mit Strings zu tun hat verwenden, wenn (String.IsNullOrEmpty (myStr))

2

Sie Codebeispiel wird scheitern. Wenn obj null ist, führt das obj.ToString() zu einer Nullreferenzausnahme. Ich würde den Prozess abkürzen und nach einem Null-Obj zu Beginn Ihrer Hilfsfunktion suchen. Was ist die Art der Frage, die Sie auf Null oder Null prüfen? Auf String gibt es eine große IsNullOrEmpty-Funktion, scheint mir das eine große Verwendung von Erweiterungsmethoden zu sein, um eine IsNullOrZero-Methode auf dem Int zu implementieren? Art.

Bearbeiten: Denken Sie daran, das '?' ist nur Compiler Zucker für den INullable-Typ, so dass Sie wahrscheinlich ein INullable als Parm nehmen und dann jsut vergleichen Sie es mit Null (Parm == null) und wenn nicht Null mit Null vergleichen.

+0

cheers für das Auffangen dieses Bugs - in diesem Projekt muss ich gegen int überprüfen ?, Doppel ?, Dezimal? Usw., weshalb ich "Objekt" verwende – nailitdown

+0

Denken Sie daran, das "?" ist nur kompilieren Zucker für die INullable Art, so könnten Sie wahrscheinlich eine INullable als Parm und dann jsut vergleichen Sie es mit null (Parm == null) und wenn nicht Null mit Null vergleichen. –

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

Ihre Lösung funktioniert für eine Eigenschaft, ich hätte angeben sollen, ich habe viele Eigenschaften des gleichen Elements auf Null/Null zu überprüfen – nailitdown

35

Verwendung von Generika:

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

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

Wenn T es ist ein Referenztyp, value mit null (default(T)), ansonsten verglichen werden, wenn T ein value type ist, lassen Sie uns doppelt sagen, default(t) ist 0d, für bool ist false, für char ist '\0' und so weiter ...

1

Gibt es einen besseren Weg?

Nun, wenn Sie wirklich nach einem besseren Weg suchen, können Sie wahrscheinlich eine weitere Ebene der Abstraktion auf Rate hinzufügen. Nun, hier ist etwas, das ich gerade mit Nullable Design Pattern entwickelt habe.

 
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

Ich denke, Sie haben Recht, dass die Beseitigung Null-Werte in einem früheren Stadium wäre der Weg zu gehen – nailitdown

+0

Nicht genau. Es gibt ein Konzept namens "Refactoring". Sie können Ihren Code in Richtung eines besseren Musters oder einer besseren Struktur umgestalten. Sie können NULL-Werte jederzeit in späteren Phasen eliminieren. – Sung

0

Vergessen Sie nicht, für Streicher, können Sie immer verwenden:

String.IsNullOrEmpty(str) 

Statt:

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

Frage vergleicht mit "0" keine leere Zeichenfolge. – Sung

16

Das ist wirklich nur eine Erweiterung der akzeptierten Antwort Freddy Rios nur Generics verwenden.

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

HINWEIS wir nicht brauchen, default (T) für null zu überprüfen, da wir entweder mit Wert zu tun haben, Typen oder structs! Dies bedeutet auch, dass wir sicher annehmen können, dass T valueToCheck nicht null ist; Denken Sie daran, dass T? ist Kurzschrift Nullable <T> so durch Hinzufügen der Erweiterung zu Nullable <T> erhalten wir die Methode in Int ?, Doppel ?, bool? usw.

Beispiele:

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

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

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

Obwohl ich ganz wie die akzeptierte Antwort, glaube ich, dass für Vollständigkeit, sollte diese Option auch erwähnt werden:

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

Diese Lösung


¹ Dies ist nicht Ihre Entscheidung, obwohl beeinflussen sollte, da diese Art von Mikro-Optimierung ist es unwahrscheinlich, einen Unterschied machen.

Verwandte Themen