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)?

161
demandé sur Peter Mortensen 2011-06-21 01:40:36

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;.

205
répondu Jon 2011-06-20 23:34:27

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;
38
répondu Jowen 2015-09-28 08:10:14

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;

}

26
répondu glosrob 2011-06-20 22:04:50

[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

16
répondu gatopeich 2012-10-25 08:52:14

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.

9
répondu Ed S. 2011-06-20 21:51:24

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>();
6
répondu Jeffrey L Whitledge 2011-06-20 21:42:19

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)

6
répondu kofifus 2018-08-22 00:27:44

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 //
   }
4
répondu combo_ci 2018-03-28 19:31:32

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) {
        //...
      }
    }
2
répondu DiableNoir 2011-06-21 08:51:07

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é.

2
répondu Michael Kjörling 2011-06-21 12:12:16
  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;
}
2
répondu Jose Ortega 2017-08-31 17:19:07

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
  }
}
1
répondu user3483639 2018-04-29 18:55:02