Considérer ce code:
String s = null;
Console.WriteLine(s.Length);
Cela permettra de jeter un NullReferenceException
dans la deuxième ligne et vous voulez savoir pourquoi .NET ne veut pas dire que cela a été s
qui est nulle lorsque la levée de l'exception.
Pour comprendre pourquoi vous n'avez pas cette information, vous devriez vous rappeler qu'il n'est pas source en C# qui s'exécute mais plutôt IL:
IL_0001: ldnull
IL_0002: stloc.0 // s
IL_0003: ldloc.0 // s
IL_0004: callvirt Système.Chaîne de caractères.get_Length
IL_0009: Système d'appel.Console.WriteLine
C'est l' callvirt
opcode qui lève l' NullReferenceException
et il n'est que lorsque le premier argument sur la pile d'évaluation est référence null (celui qui a été chargé à l'aide d' ldloc.0
).
Si .NET devrait être en mesure de dire qu'il a été s
qui a été une référence null, il doit, d'une certaine façon que le premier argument sur la pile d'évaluation provient forme s
. Dans ce cas, il est facile pour nous de voir que c'est l' s
que c'était nul mais que faire si la valeur est une valeur de retour à partir d'un autre appel de fonction et de ne pas stocké dans une variable? De toute façon, ce genre d'information n'est pas ce que vous voulez garder une trace de dans une machine virtuelle comme le .NET de la machine virtuelle.
Pour éviter ce problème, je vous suggère d'effectuer argument null vérification dans tous les appels de méthode (sauf si bien sûr vous permettre la référence nulle):
public void Foo(String s) {
if (s == null)
throw new ArgumentNullException("s");
Console.WriteLine(s.Length);
}
Si la valeur null est passé à la méthode, vous obtenez une exception précisément quel est le problème (qui s
est null).