La référence d’object n’est pas définie sur une instance d’object. Pourquoi .NET ne montre-t-il pas quel object est “null”?

En ce qui concerne ce message d’exception non géré .NET:

La référence d’object n’est pas définie à une instance d’un object.

Pourquoi .NET ne montre-t-il pas quel object est null ?

Je sais que je peux vérifier la null et résoudre l’erreur. Cependant, pourquoi .NET ne vous aide-t-il pas à indiquer quel object a une référence null et quelle expression a déclenché l’ NullReferenceException ?

(Pour plus d’informations sur le nouvel assistant d’exception dans Visual Studio 2017, reportez-vous à la fin de cette réponse)


Considérez ce code:

 Ssortingng s = null; Console.WriteLine(s.Length); 

Cela lancera une NullReferenceException dans la deuxième ligne et vous voulez savoir pourquoi .NET ne vous dit pas que c’était s qui était nul lorsque l’exception a été lancée.

Pour comprendre pourquoi vous n’obtenez pas cette information, vous devez vous rappeler que ce n’est pas la source C # qui s’exécute, mais plutôt IL:

 IL_0001: lnnull      
 IL_0002: stloc.0 // s
 IL_0003: ldloc.0 // s
 IL_0004: callvirt System.Ssortingng.get_Length
 IL_0009: appelez System.Console.WriteLine

C’est l’opcode callvirt qui lève le NullReferenceException et il le fait lorsque le premier argument de la stack d’évaluation est une référence null (celle qui a été chargée avec ldloc.0 ).

Si .NET devrait être en mesure de dire que c était une référence NULL, il devrait suivre d’une manière ou d’une autre que le premier argument de la stack d’évaluation provient des formulaires s . Dans ce cas, il est facile pour nous de voir que c’est s qui était nul mais que se passerait-il si la valeur était une valeur de retour d’un autre appel de fonction et non stockée dans une variable? Quoi qu’il en soit, ce type d’information n’est pas ce que vous souhaitez conserver dans une machine virtuelle telle que la machine virtuelle .NET.


Pour éviter ce problème, je suggère que vous effectuiez la vérification de l’argument null dans tous les appels de méthodes publiques (sauf si vous autorisez bien sûr la référence null):

 public void Foo(Ssortingng s) { if (s == null) throw new ArgumentNullException("s"); Console.WriteLine(s.Length); } 

Si null est transmis à la méthode, vous obtenez une exception qui décrit précisément le problème (c’est s nul).


Quatre ans plus tard, Visual Studio 2017 dispose désormais d’un nouvel assistant d’exception qui tentera de déterminer ce qui est nul lorsqu’une NullReferenceException est lancée. Il est même capable de vous donner les informations requirejses lorsque c’est la valeur de retour d’une méthode qui est nulle:

Assistant d'exception Visual Studio 2017

Notez que cela ne fonctionne que dans une version DEBUG.

Comment voulez-vous que le message d’erreur dans le cas suivant ressemble à?

 AnyObject.GetANullObject().ToSsortingng(); private object GetANullObject() { return null; } 

Pas de noms de variables à signaler ici!

Eh bien, ce n’est que des ingénieurs chez Microsoft pour répondre. Mais vous pouvez évidemment utiliser un débogueur et append une surveillance pour savoir lequel a un problème.

Cependant, l’exception est NullReferenceException ce qui signifie que la référence n’existe pas . Vous ne pouvez pas obtenir l’object qui n’a pas été créé du tout.

but why .NET don't tell us which object is null? Parce qu’il ne sait pas quel object est nul. L’object n’existe tout simplement pas!

Le même est le cas lorsque je dis, C # est compilé en code .NET IL. Le code .NET IL ne connaît pas les noms ou les expressions. Il ne connaît que les références et leur emplacement. Ici aussi, vous ne pouvez pas obtenir ce qui n’existe pas. L’expression ou le nom de la variable n’existe pas.

Philosophie: Vous ne pouvez pas faire une omelette si vous n’avez pas d’œuf en premier lieu.

Pas sûr, mais c’est peut-être parce que .Net ne sait pas si c’est une classe prédéfinie ou définie par l’utilisateur. S’il est prédéfini, il peut être nul (comme une chaîne qui occupe 2 octets), mais s’il est défini par l’utilisateur, il faut en créer une instance pour qu’il sache que cet object occupera autant de mémoire. Par conséquent, il génère une erreur au moment de l’exécution.

Bonne question. La boîte de message est tout simplement inutile. Même si elle est enfouie à un mille de la définition des références, une classe, un assemblage, un fichier ou d’autres informations seraient meilleurs que ce qu’ils fournissent actuellement (lisez: mieux que rien).

Votre meilleure option est de l’exécuter dans le débogueur avec des informations de débogage, et votre IDE se cassera au niveau de la ligne incriminée (démontrant clairement que des informations utiles sont en fait disponibles).