この .NET 未処理の例外メッセージについて:
オブジェクト参照がオブジェクト インスタンスに設定されていません。
.NET でどのオブジェクトが であるかが表示されないのはなぜnull
ですか?
null
エラーを確認して解決できることはわかっています。しかし、なぜ .NET はどのオブジェクトがヌル参照を持ち、どの式がNullReferenceException
.
(Visual Studio 2017 の新しい例外ヘルパーについては、この回答の最後を参照してください)
次のコードを検討してください。
String s = null;
Console.WriteLine(s.Length);
これにより、2 行目に a がスローされます。例外がスローされたときに .NET がそれが nullNullReferenceException
であったことを通知しない理由を知りたいと考えています。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
あり、評価スタックの最初の引数が null 参照 (を使用してロードされたものldloc.0
) である場合にそれを行います。
.NET がそれがs
null 参照であったことを認識できる場合、何らかの方法で、評価スタックの最初の引数がフォームから発生したことを追跡する必要がありますs
。この場合、null だったことは簡単にわかりs
ますが、値が別の関数呼び出しからの戻り値であり、変数に格納されていない場合はどうなるでしょうか。とにかく、この種の情報は、.NET 仮想マシンのような仮想マシンで追跡したいものではありません。
この問題を回避するには、すべてのパブリック メソッド呼び出しで引数の null チェックを実行することをお勧めします (もちろん、null 参照を許可しない限り)。
public void Foo(String s) {
if (s == null)
throw new ArgumentNullException("s");
Console.WriteLine(s.Length);
}
null がメソッドに渡されると、問題の内容を正確に説明する例外が発生します (つまりs
、null です)。
NullReferenceException
4 年後、Visual Studio 2017 には、 aがスローされたときに何が null であるかを伝えようとする新しい例外ヘルパーが含まれています。メソッドの戻り値が null の場合でも、必要な情報を提供できます。
これは DEBUG ビルドでのみ機能することに注意してください。
次の場合のエラー メッセージをどのように表示しますか?
AnyObject.GetANullObject().ToString();
private object GetANullObject()
{
return null;
}
ここに報告する変数名はありません!
まあ、それはマイクロソフトのエンジニア次第です。しかし、明らかにデバッガーを使用してウォッチを追加し、それらのどれに問題があるかを見つけることができます。
ただし、例外はNullReferenceException
、参照が存在しないことを意味します。まったく作成されていないオブジェクトを取得することはできません。
but why .NET don't tell us which object is null?
どのオブジェクトが null であるかがわからないためです。オブジェクトは単に存在しません!
C# は .NET IL コードにコンパイルされると言う場合も同様です。.NET IL コードは、名前または式を認識しません。参照とその場所のみを認識します。ここでも、存在しないものは得られません。式または変数名が存在しません。
理念:そもそも卵がないとオムレツは作れない。