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?
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
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. ..
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
((item.Rate ?? 0) == 0)
(cela pourrait être une question de goût, cependant).¹ Cela ne devrait toutefois pas influer sur votre décision, car ce type de micro-optimisation ne fera probablement aucune différence.
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
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) {} } }
Je suis d'accord pour utiliser le ?? opérateur.
Si vous avez affaire à des chaînes, utilisez if (String.IsNullOrEmpty (myStr))
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.
N'oubliez pas que pour les chaînes, vous pouvez toujours utiliser:
String.IsNullOrEmpty(str)
Au lieu de:
str==null || str==""
public static bool nz(object obj)
{
return obj == null || obj.Equals(Activator.CreateInstance(obj.GetType()));
}
class Item{
bool IsNullOrZero{ get{return ((this.Rate ?? 0) == 0);}}
}
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));
}
}