Types nullables: meilleur moyen de vérifier la valeur null ou zero en c #
Question
Je travaille sur un projet dans lequel je constate que je vérifie les éléments suivants dans de très 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?
La solution
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
Autres conseils
Utilisation des 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
c'est un type de référence , value
sera comparé à null
(default(T)
), sinon, si value type
est un default(t)
, disons double , false
est 0d, pour bool est '\0'
, pour char est <=> 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
- ne nécessite pas de méthode supplémentaire,
- est plus rapide que toutes les autres options, car GetValueOrDefault est une opération de lecture de champ unique & # 185; et
- lit plus facilement que
((item.Rate ?? 0) == 0)
(cela peut être une question de goût, cependant).
& # 185; 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));
}
REMARQUE , nous 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 un raccourci Nullable < T > donc en ajoutant l'extension à Nullable < T > nous obtenons la méthode dans int ?, double ?, bool? etc.
Exemples:
double? x = null;
x.IsNullOrDefault(); //true
int? y = 3;
y.IsNullOrDefault(); //false
bool? z = false;
z.IsNullOrDefault(); //true
Je suis d'accord avec l'utilisation de la ?? opérateur.
Si vous traitez avec des chaînes, utilisez if (String.IsNullOrEmpty (myStr))
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 { 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) { } } }
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. Cela me semble 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 jsut le comparer à null (parm == null) et, si ce n’est pas nul, comparer à zéro.
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);}}
}
N'oubliez pas que pour les chaînes, vous pouvez toujours utiliser:
String.IsNullOrEmpty(str)
Au lieu de:
str==null || str==""
Encore un peu plus loin que Joshua Shannon réponse . Désactivez maintenant la prévention 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));
}
}