web-dev-qa-db-fra.com

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 null par:

if (!data.Equals(null))

et

if (data != null)

Cependant, je reçois un NullReferenceException sur dataList.Add(data). Si l'objet était null, il n'aurait même jamais dû entrer l'instruction if-!

Donc, je demande si c'est une bonne façon de vérifier si un objet est nul:

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 le moyen approprié de vérifier si l'objet est null, qu'est-ce que je fais de mal (comment puis-je empêcher tout traitement ultérieur sur l'objet pour éviter l'exception NullReferenceException)?

187
developer

Ce n'est pas data c'est null, mais dataList.

Vous devez en créer un avec

public List<Object> dataList = new List<Object>();

Mieux encore: puisque c'est un champ, donnez-le private. Et si rien ne vous empêche, faites-le aussi readonly. Juste une bonne pratique.

à part

La méthode correcte pour 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 qu'il soit un moyen plus pratique d'exprimer nullable.HasValue lors de la vérification de la nullité.

Si vous faites if(!data.Equals(null)) alors vous obtiendrez un NullReferenceException if data == null. Ce qui est un peu comique, puisque l’objectif premier était d’éviter cette exception.

Vous faites aussi ceci:

catch (Exception e)
{
    throw new Exception(e.ToString());
}

Ce n'est vraiment pas bon. J'imagine que vous le mettez juste pour pouvoir entrer dans le débogueur tout en restant dans la méthode, auquel cas ignorer ce paragraphe. Sinon, ne détectez aucune exception pour rien. Et si vous le faites, relancez-les en utilisant simplement throw;.

228
Jon

C # 6 a vérification null 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;
48
Jowen

en C # 7 le meilleur est

if (obj is null) ...

Cela ignorera tout == ou! = Défini par l'objet (sauf si vous voulez bien sûr les utiliser ...)

Pour pas égal, vous pouvez if (!(obj is null)) (laid)

32
kofifus

Votre liste de données est nulle car elle n'a pas été instanciée, à en juger par le code que vous avez posté.

Essayer:

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;

}

27
glosrob

[(Modifié pour refléter l'allusion de @ kelton52])

Le moyen le plus simple est de faire object.ReferenceEquals(null, data)

Puisque (null==data) n'est PAS garanti de 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:

Comparer avec Nully

Vrai

False

17
gatopeich

Non, vous devriez utiliser !=. Si data est réellement nul, votre programme plantera juste avec un NullReferenceException à la suite d'une tentative d'appel de la méthode Equals sur null. Sachez également que, si vous souhaitez vérifier spécifiquement l’égalité des références, vous devez utiliser la méthode Object.ReferenceEquals car vous ne savez jamais comment Equals a été implémenté.

Votre programme plante, car dataList est nul car vous ne l'initialisez jamais.

9
Ed S.

Le problème dans ce cas n’est pas que data soit null. C'est que dataList elle-même est nulle.

À l'endroit où vous déclarez dataList, vous devez créer un nouvel objet List et l'assigner à la variable.

List<object> dataList = new List<object>();
6

En plus de @ Jose Ortega answer, il est préférable de l'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 tels que:

object foo = new object(); //or any object from any class
if (foo.IsNull())
   {
     // blah blah //
   }
5
Ali
  public static bool isnull(object T)
  {
      return T == null ? true : false;
  }

utilisation:

isnull(object.check.it)

Usage conditionnel:

isnull(object.check.it) ? DoWhenItsTrue : DoWhenItsFalse;

Mise à jour (autre moyen) mise à jour le 31/08/2017. Merci pour le commentaire.

public static bool isnull(object T)
{
    return T ? true : false;
}
2
Jose Ortega

Jeffrey L. Whitledge a raison. Votre objet 'dataList´ lui-même est nul.

Il y a aussi un autre problème avec votre code: vous utilisez le mot-clé ref, ce qui signifie que l'argument data ne peut 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 nécessairement être explicitement initialisés avant d'être passés

Il est également déconseillé d’utiliser des médicaments génériques avec le type "Object". Les génériques doivent éviter la boxing/unboxing et également garantir 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) {
        //...
      }
    }
2
DiableNoir

Comme d'autres l'ont déjà fait remarquer, ce n'est pas data mais plutôt dataList c'est null. En plus de ça...

catch-throw est un anti-modèle 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 récupérez est un objet Exception, jeté sur le throw dans AddData(). Aucune trace de pile, aucune information sur les appels, aucun état, rien du tout pour indiquer la source réelle du problème, à moins que vous ne basculiez dans le débogueur pour qu'il interrompe une exception levée plutôt qu'une exception non gérée. Si vous attrapez une exception et que vous la relancez de quelque manière que ce soit, en particulier si le code dans le bloc try est en quelque sorte non trivial, faites-vous une faveur (et à vos collègues, présents et futurs) et jetez tout le bloc try-catch. Certes, throw; est préférable aux solutions de rechange, mais vous vous donnez toujours (ou à quiconque tente de réparer un bogue dans le code) des maux de tête complètement inutiles. 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 exception qui a été lancé dans le bloc catch.

Il y a ensuite les problèmes potentiels liés à la capture de Exception en premier lieu, mais c’est un autre problème, 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 data pourrait potentiellement changer de valeur pendant l'exécution de la fonction, puisque vous passez par référence. Donc, la vérification de null peut passer mais avant que le code ne fasse quoi que ce soit avec la valeur, il a été changé - peut-être en null. Je ne suis pas certain si cela vous préoccupe ou non (ce n'est peut-être pas le cas), mais cela semble valoir la peine d'être surveillé.

2
a CVn

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: objet1 est objet de classe

void myFunction(object1)
{
  if(object1!=null)
  {
     object1.value1 //If we miss the null check then here we get the Null Reference exception
  }
}
1
user3483639

Je viens de suivre une méthode que nous suivions habituellement dans le script Java. Pour convertir un objet en chaîne, puis vérifier s’ils sont nuls.

var obj = new Object();
var objStr = obj.ToString();
if (!string.IsNullOrEmpty(objStr)){
  // code as per your needs
}
0
Mohan Stanky