Vérifier si un objet est null en C#
Je voudrais empêcher tout traitement ultérieur sur un objet s'il est nul.
Dans le code suivant, je vérifie si l'objet est nul:
if (!data.Equals(null))
Et
if (data != null)
Cependant, je reçois un NullReferenceException
à dataList.Add(data)
. Si l'objet était null, il n'aurait même jamais dû entrer l'instruction if
-!
Ainsi, je demande si c'est une bonne façon de vérifier si un objet est null:
public List<Object> dataList;
public bool AddData(ref Object data)
bool success = false;
try
{
// I've also used "if (data != null)" which hasn't worked either
if (!data.Equals(null))
{
//NullReferenceException occurs here ...
dataList.Add(data);
success = doOtherStuff(data);
}
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
return success;
}
Si c'est la bonne façon de vérifier si l'objet est null, ce que je fais mal (Comment puis-je empêcher un traitement ultérieur sur l'objet pour éviter L'exception NullReferenceException)?
12 réponses
Pas data
est null
, mais dataList
.
, Vous devez en créer un avec
public List<Object> dataList = new List<Object>();
Encore mieux: puisque c'est un champ, faire private
. Et s'il n'y a rien qui vous empêche, faites-le aussi readonly
. Juste de la bonne pratique.
À part
La bonne façon de vérifier la nullité est if(data != null)
. Ce type de vérification est omniprésent pour les types de référence; même Nullable<T>
remplace l'opérateur d'égalité pour être un moyen plus pratique d'exprimer nullable.HasValue
lors de la vérification nullité.
Si vous ne if(!data.Equals(null))
, alors vous obtiendrez un NullReferenceException
si data == null
. Ce qui est un peu comique car éviter cette exception était le but en premier lieu.
Vous faites aussi ceci:
catch (Exception e)
{
throw new Exception(e.ToString());
}
Ce n'est certainement pas bon. Je peux imaginer que vous l'avez mis là juste pour que vous puissiez pénétrer dans le débogueur tout en restant dans la méthode, auquel cas ignorer ce paragraphe. Sinon, n'attrapez pas les exceptions pour rien. Et si vous le faites, repensez-les en utilisant juste throw;
.
C # 6 A vérification nulle monadique :)
Avant:
if (points != null) {
var next = points.FirstOrDefault();
if (next != null && next.X != null) return next.X;
}
return -1;
Après:
var bestValue = points?.FirstOrDefault()?.X ?? -1;
Votre dataList est nul car il n'a pas été instancié, à en juger par le code que vous avez posté.
Essayez:
public List<Object> dataList = new List<Object>();
public bool AddData(ref Object data)
bool success = false;
try
{
if (!data.Equals(null)) // I've also used if(data != null) which hasn't worked either
{
dataList.Add(data); //NullReferenceException occurs here
success = doOtherStuff(data);
}
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
return success;
}
[Modifié pour refléter indice par @kelton52]
Plus Simple est de faire object.ReferenceEquals(null, data)
Puisque (null==data)
n'est pas garanti pour fonctionner:
class Nully
{
public static bool operator ==(Nully n, object o)
{
Console.WriteLine("Comparing '" + n + "' with '" + o + "'");
return true;
}
public static bool operator !=(Nully n, object o) { return !(n==o); }
}
void Main()
{
var data = new Nully();
Console.WriteLine(null == data);
Console.WriteLine(object.ReferenceEquals(null, data));
}
Produit:
Comparaison "avec' Nully '
Vrai
Faux
Non, vous devriez utiliser !=
. Si data
est réellement null, votre programme va simplement planter avec un NullReferenceException
à la suite d'une tentative d'appeler la méthode Equals
sur null
. Réalisez également que, si vous voulez spécifiquement vérifier l'égalité de référence, vous devez utiliser la méthode Object.ReferenceEquals
car vous ne savez jamais comment Equals
a été implémenté.
Votre programme se bloque car dataList
est nul car vous ne l'initialisez jamais.
Le problème dans ce cas n'est pas que data
est nulle. C'est que dataList
lui-même est nulle.
À l'endroit où vous déclarez dataList
vous devez créer un nouveau List
objet et l'affecter à la variable.
List<object> dataList = new List<object>();
En C # 7 le meilleur est
if (obj is null)
...
Cela ignorera tout = = ou!= défini par l'objet (sauf si bien sûr vous voulez les utiliser ...)
Pour pas égal, vous pouvez if (!(obj is null))
(laid)
En plus de @José Ortega répondre, de son mieux pour utiliser méthode d'extension
public static bool IsNull(this object T)
{
return T == null;
}
Et utilisez la méthode IsNull
pour tous les objets comme:
object foo = new object(); //or any object from any class
if (foo.IsNull())
{
// blah blah //
}
Jeffrey l Whitledge a raison. Votre ' dataList-Object lui-même est null.
Il y a aussi un autre problème avec votre code: vous utilisez le mot-clé ref, ce qui signifie que les données de l'argument ne peuvent pas être null! Le MSDN dit:
Un argument passé à un paramètre ref doit d'abord être initialisé. Cela diffère de out, dont les arguments ne doivent pas être explicitement initialisés avant d'être passés
Ce n'est pas non plus une bonne idée d'utiliser des génériques avec l'objet type`. Les génériques devraient éviter la boxe/unboxing et également assurer la sécurité du type. Si vous voulez un type commun, rendez votre méthode générique. Enfin, votre code devrait ressembler à ceci:
public class Foo<T> where T : MyTypeOrInterface {
public List<T> dataList = new List<T>();
public bool AddData(ref T data) {
bool success = false;
try {
dataList.Add(data);
success = doOtherStuff(data);
} catch (Exception e) {
throw new Exception(e.ToString());
}
return success;
}
private bool doOtherStuff(T data) {
//...
}
}
Comme d'autres l'ont déjà souligné, il n'est pas data
, mais plutôt probable dataList
est null
. En plus de cela...
catch
-throw
est un antipattern qui me donne presque toujours envie de vomir chaque fois que je le vois. Imaginez que quelque chose ne va pas au fond de quelque chose que doOtherStuff()
appelle. Tout ce que vous obtenez est un objet Exception
, jeté sur le throw
dans AddData()
. Aucune trace de pile, aucune information d'appel, aucun État, rien du tout pour indiquer la source réelle du problème, sauf si vous entrez et basculez votre débogueur pour casser l'exception levée plutôt que l'exception non gérée. Si vous attrapez une exception et que vous la lancez simplement de quelque manière que ce soit, en particulier si le code du bloc try est de quelque manière non trivial, faites-vous (et vos collègues, présents et futurs) une faveur et jetez l'ensemble try
-catch
bloc. Certes, throw;
est meilleur que les alternatives, mais vous vous donnez toujours (ou quiconque essaie de corriger un bug dans le code) complètement inutile mal. Cela ne veut pas dire que try-catch-throw est nécessairement mauvais en soi, tant que vous faites quelque chose de pertinent avec l'objet d'exception qui a été lancé à l'intérieur du bloc catch.
Ensuite, il y a les problèmes potentiels d'attraper Exception
en premier lieu, mais c'est une autre question, d'autant plus que dans ce cas particulier, vous lancez une exception.
Une autre chose qui me semble plus qu'un peu dangereuse est que {[0] } pourrait potentiellement changer de valeur pendant l'exécution de la fonction, puisque vous passez par référence. Donc, la vérification null peut passer mais avant que le code ne fasse quoi que ce soit avec la valeur, il est changé - peut-être en null
. Je ne suis pas positif si c'est une préoccupation ou non (ce n'est peut-être pas le cas), mais cela vaut la peine d'être surveillé.
public static bool isnull(object T)
{
return T == null ? true : false;
}
Utilisation:
isnull(object.check.it)
Utilisation conditionnelle:
isnull(object.check.it) ? DoWhenItsTrue : DoWhenItsFalse;
Mise à jour (une autre façon) mise à jour 08/31/2017. Merci pour le commentaire.
public static bool isnull(object T)
{
return T ? true : false;
}
Chaque fois que vous créez des objets de classe, vous devez vérifier si l'objet est null ou non en utilisant le code ci-dessous.
Exemple: object1 est l'objet de la classe
void myFunction(object1)
{
if(object1!=null)
{
object1.value1 //If we miss the null check then here we get the Null Reference exception
}
}