青柳臣一 blog : .NET や C# がメインの blog

.NET や C# がメインの blog
投稿数 - 548, コメント - 272, トラックバック - 205

Nullable Boxing

TechEd 2005 Yokohama の初日(8月2日)の 「L3-1 C# 2.0 and IDE Tips & Tricks Part1」 のセッションで言われていたことです。スピーカーの波村さんによると 「今日から公開していいと言われた内容です。このデザインチェンジが行われたのは、ここ 1ヵ月半くらいのことです」 ということです。

で、どういったデザインチェンジかというと、
 void Foo<T>(T t)
 {
   Console.WriteLine("Foo<T>: {0}", t == null);
 }
 void Test()
 {
   int? i = null;
   Foo(i);
   Console.WriteLine("i == null: {0}", i == null);
   Console.WriteLine("(object)i == null: {0}", (object)i == null);
 }
これを実行するとどうなるか?という部分です。

実際に beta2 で実行すると
 Foo<T>: False
 i == null: True
 (object)i == null: False
となります。

  • 最初の Foo<T> では T は当然 int? となっています。問題は t == null の部分ですが、この部分の JIT による解釈は 「int? は値型の一種。値型は null には成り得ない。だから常に false」 ということになるそうです (波村さんに聞いたらこんな風におっしゃってたと思います)。int? は Nullable<int> ですし、Nullable<T> は struct ですから、「値型の一種」 というより値型そのものですね。だから null にならないのは当然とも言えます。(と思う。こういう解釈であってるのかな?)
  • 2番目の i == null は C# コンパイラが i.HasValue を呼び出すべきということを判断できます。なので、そのような IL が出力されます(実際に ildasm で見てみると i.HasValue を呼び出しているのがわかります)。
  • 最後の (object)i == null も Foo<T> と同じような感じで i を box 化して null と比較する IL が生成されます。だからこれは常に false です。

これはこれで正しいわけですが、やはりわかりにくいしバグの元でもあるので 「なんとかしようよ」 ということになったそうです。どうなんとかするかと言うと、「nullable を box 化したときに元が null であればちゃんと null になる(null と比較したとき true になる)」 となるようにしたってことでした。これによって、
 Foo<T>: True
 i == null: True
 (object)i == null: True
となることになります。

あと、
  int? i = null;
  object o = i;
  Console.WriteLine("o is int: {0}", o is int);
  Console.WriteLine("o is int?: {0}", o is int?);
の結果が
 o is int: True
 o is int?: True
となるようにも変更されるとのことでした。
beta2 では
  int? i = 1;
  int x = (int)i;
というコードをコンパイルできます。これは C# コンパイラによって
  int x = i.Value;
と解釈されています(IL を見るとそうなってます)。さて、それでは、
  int? i = 1;
  object o = i;
  int x = (int)o;
はどうでしょうか?これは beta2 では実行時エラーが発生します。o に格納されているのは box 化された int? なので int にキャストすることはできません。これを実行可能にするには、
  int x = (int)(int?)o;
のように int? にキャストしてから int にキャストしてやる必要があります。結局、int? を直接 int にキャストすることはできるのに、いったん box 化すると int にキャストすることはできなくなる、というふうに見えることになります。これが上記のように 「int? を box 化したものは int? でもあり int でもある」 となれば問題なく
  int? i = 1;
  object o = i;
  int x = (int)o;
というコードを実行できることになります。。。ということであってるのかなぁ?

まだ実際の処理系がないので、いまいち合ってるのかどうか自信はありませんが、こんなような感じみたいです。

投稿日時 : 2005年8月10日 19:39

トラックバックは下記のURLにpingを送信してください。
TrackBack URL: http://www.divakk.co.jp/blog/aoyagi/services/trackbacks/6962.aspx

フィードバック

# Nullable Type の仕様変更

Nullable Boxinghttp://www.divakk.co.jp/blog/aoyagi/archive/2005/08/10/6962.aspx
Nullable Boxing その2http://www.divakk.co.jp/blog/aoyagi/archive/2005/08/18/6977.aspx...
2005/08/19 1:13 | HIDORI on The Web: 渋木宏明(ひどり) blog (トラックバック)

コメントの投稿

タイトル  
名前  
URL
コメント   
Protected by Clearscreen.SharpHIPこの絵に表示されている文字列を入力してください (半角で4文字です):