web-dev-qa-db-fra.com

Types nullables: meilleur moyen de vérifier la valeur null ou zero en c #

Je travaille sur un projet dans lequel je constate que je vérifie les éléments suivants dans de nombreux endroits:

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

plus comme une curiosité qu'autre chose, quel est le meilleur moyen de vérifier les deux cas?

J'ai ajouté une méthode d'assistance qui est:

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

Y a-t-il un meilleur moyen?

65
nailitdown

J'aime if ((item.Rate ?? 0) == 0) { } 

Mise à jour 1:

Vous pouvez également définir une méthode d'extension telle que:

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

Et utilisez-le comme ceci: 

if(item.IsNullOrValue(0)){} // mais vous n'en tirez pas grand chose

130
eglasius

Utilisation de génériques: 

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

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

Si T est un type de référence, value sera comparé à null (default(T)), sinon, si T est un value type, disons double, default(t) est 0d, car bool est false, car char est '\0' et ainsi de suite. ..

38
CMS

Bien que j'aime bien la réponse acceptée, je pense que, pour être complet, cette option devrait également être mentionnée:

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

Cette solution


¹ Cela ne devrait toutefois pas influer sur votre décision, car ce type de micro-optimisation ne fera probablement aucune différence.

26
Heinzi

Il s’agit en réalité d’une extension de la réponse acceptée par Freddy Rios, qui utilise uniquement des médicaments génériques.

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

NOTEnous n'avons pas besoin de vérifier la valeur null par défaut (T) car nous avons affaire à des types de valeur ou à des structs! Cela signifie également que nous pouvons supposer que T valueToCheck ne sera pas nul; Tu te souviens ici que T? est abrégé Nullable <T> donc en ajoutant l'extension à Nullable <T> nous obtenons la méthode en int ?, double ?, bool? etc.

Exemples:

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

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

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

y a-t-il un meilleur moyen?

Eh bien, si vous cherchez vraiment un meilleur moyen, vous pouvez probablement ajouter une autre couche d’abstraction au-dessus de Rate. Eh bien voici quelque chose que je viens de proposer avec Nullable Design Pattern.

 using System; 
 using System.Collections.Generic; 

 namespace NullObjectPatternTest 
 {
 Programme de classe publique 
 {
 public static void Main (string [] args) 
 {
 var items = nouvelle liste 
 {
 nouvel élément (RateFactory.Create (20)), 
 nouvel élément (RateFactory.Create (null)) 
 }; 

 PrintPricesForItems (items); 
 } 

 voic statique privé PrintPricesForItems (éléments IEnumerable) 
 {
 foreach (var item dans items) 
 Console.WriteLine ("Prix de l'article: {0: C}", item.GetPrice ()); 
 } 
 } 

 classe abstraite publique ItemBase 
 {
 abstract public Rate Rate {get; } 
 public int GetPrice () 
 {
 // Il n'est PAS nécessaire de vérifier si Rate == 0 ou Rate == null 
 return 1 * Rate.Value; 
 } 
 } 

 Classe publique Item: ItemBase 
 {
 privé en lecture seule Rate _Rate; 
 remplacement public Rate Rate {get {return _Rate; }} 
 élément public (taux) {_Rate = rate; } 
 } 

 classe scellée publique RateFactory 
 {
 public static Rate Create (int? rateValue) 
 {
 if (! rateValue || rateValue == 0) 
 renvoie new NullRate (); 
 renvoyer un nouveau taux (rateValue); 
 } 
 } 

 Classe publique Tarif 
 {
 public int Value {get; ensemble; } 
 public virtuel bool HasValue {get {return (valeur> 0); }} 
 taux public (valeur int) {valeur = valeur; } 
 } 

 Classe publique NullRate: Rate 
 {
 public override bool HasValue {get {return false; }} 
 public NullRate (): base (0) {} 
 } 
} 
2
Sung M. Kim

Je suis d'accord pour utiliser le ?? opérateur. 

Si vous avez affaire à des chaînes, utilisez if (String.IsNullOrEmpty (myStr))

2
Nick Josevski

Votre exemple de code échouera. Si obj est null, alors obj.ToString () donnera une exception de référence null. Je raccourcirais le processus et rechercherais un obj nul au début de votre fonction d'assistance. En ce qui concerne votre question, quel est le type que vous recherchez pour null ou zéro? Sur String, il existe une excellente fonction IsNullOrEmpty. Il me semble que ce serait une excellente utilisation des méthodes d'extension pour implémenter une méthode IsNullOrZero sur l'int? type.

Edit: Rappelez-vous, le '?' est juste un sucre de compilateur pour le type INullable, vous pouvez donc probablement prendre un INullable comme paramètre, puis le comparer à null (parm == null) et s’il n’est pas nul, comparer à zéro. 

2
Walden Leverich

N'oubliez pas que pour les chaînes, vous pouvez toujours utiliser:

String.IsNullOrEmpty(str)

Au lieu de:

str==null || str==""
0
Chris
public static bool nz(object obj)
{
    return obj == null || obj.Equals(Activator.CreateInstance(obj.GetType()));
}
0
Shea
class Item{  
 bool IsNullOrZero{ get{return ((this.Rate ?? 0) == 0);}}
}
0
dtroy

Un pas de plus de Joshua Shannon 's's Nice answer . Maintenant avec empêchant boxing/unboxing :

public static class NullableEx
{
    public static bool IsNullOrDefault<T>(this T? value)
        where T : struct
    {
        return EqualityComparer<T>.Default.Equals(value.GetValueOrDefault(), default(T));
    }
}
0
Deilan