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;
というコードを実行できることになります。。。ということであってるのかなぁ?
まだ実際の処理系がないので、いまいち合ってるのかどうか自信はありませんが、こんなような感じみたいです。
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。