(Інформацію про нового помічника винятків у Visual Studio 2017 див. У кінці цієї відповіді)
Розглянемо цей код:
String s = null;
Console.WriteLine(s.Length);
Це викине a NullReferenceExceptionу другому рядку, і ви хочете знати, чому .NET не каже вам, що це sбуло недійсно, коли викид був викинутий.
Щоб зрозуміти, чому ви не отримуєте цю інформацію, слід пам’ятати, що не джерело C # виконує, а IL:
IL_0001: ldnull
IL_0002: stloc.0 // s
IL_0003: ldloc.0 // s
IL_0004: callvirt System.String.get_Length
IL_0009: виклик System.Console.WriteLine
Саме callvirtопкод викидає NullReferenceExceptionі робить це, коли перший аргумент на стеці оцінювання є нульовою посиланням (той, який було завантажено за допомогою ldloc.0).
Якщо .NET повинен бути в змозі сказати, що це була sнульова посилання, то якимось чином слід було б відслідковувати, що перший аргумент на стеці оцінювання виник у формі s. У цьому випадку нам легко побачити, що це sбуло недійсно, але що робити, якщо це значення було зворотним значенням з іншого виклику функції і не зберігалося в жодній змінній? У будь-якому випадку, така інформація не є тим, що ви хочете відслідковувати у віртуальній машині, як віртуальна машина .NET.
Щоб уникнути цієї проблеми, я пропоную вам виконати перевірку нульових аргументів у всіх загальнодоступних викликах методу (якщо, звичайно, ви не дозволяєте нульової посилання):
public void Foo(String s) {
if (s == null)
throw new ArgumentNullException("s");
Console.WriteLine(s.Length);
}
Якщо null передається методу, ви отримуєте виняток, який точно описує, у чому полягає проблема (тобто snull).
Через чотири роки у Visual Studio 2017 тепер є новий помічник винятку, який спробує сказати, що є нульовим при киданні a NullReferenceException. Він навіть може надати вам необхідну інформацію, коли значення, що повертається, є нульовим:

Зауважте, що це працює лише у складі DEBUG.