10

同僚からこんなクイズをもらいました。このコード スニペットの場合:

var x = new Int32?();
string text = x.ToString(); // No exception
Console.WriteLine(text);
Type type = x.GetType(); // Bang!

最初の部分 .ToString() が例外をスローせずに機能し、次に GetType() の呼び出しが NullReferenceException をスローするのはなぜですか?

4

1 に答える 1

19

ToStringは でオーバーライドさNullable<T>れるため、呼び出しを行うためにボクシングは必要ありません。

GetType()は仮想メソッドではないため、オーバーライドされません (また、オーバーライドできません)。そのため、呼び出しが行われる前に値がボックス化されます...そして、null 許容値型の null 値をボックス化すると、null 参照が与えられます。

ボックス化の理由は、C# 4 仕様のセクション 7.5.5 にあります。

参照型Mで宣言されたインスタンス関数メンバーの場合:

  • ...
  • の型がEvalue -typeの場合、ボックス化変換 (4.3.1) が実行されて type に変換Eされ、次の手順で型objectE見なされobjectます。この場合、MのメンバーにしかなれませんSystem.Object

次の場合に注意してください。

var x = new Int32?(10);

typeof(int)再びボクシングのために、タイプが と同じになってしまいます。通常の方法を使用して、null 許容値型を返すfooような値を作成する方法はありません。(もちろん、新しいメソッドを作成することもできますが、それは副次的な問題です:)foo.GetType()GetType() GetType()

(「Bang!」の使用は、このクイズの作成者が私である可能性を示唆しています。そうであれば、気が狂ってしまったことをお詫びします。)

于 2012-10-04T10:50:09.933 に答える