ページ

2007年8月10日金曜日

Re: VB : "Is Nothing" vs "= Nothing" と Nullable Type の強化

Shizuku Blog さんの 「VB : "Is Nothing" vs "= Nothing" と Nullable Type の強化」 を読んでちょっとおもしろそうだったので試してみました。
VB9 の LINQ では "Is Nothing" と書いた場合と "= Nothing" と書いた場合とで同じように振舞う、とのことですが、何がどうなっているのでしょうか?


以下、Visual Studio 2008 beta 2 で試してます。

まずはもっともシンプルそうなコードで。

    Dim ary As Integer?() = {1, 2, Nothing}
    Dim query = From x In ary _
                Where x = Nothing _
                Select x
    Console.WriteLine(query.Count())

これを実行してみると、、、あれ?ちゃんと "0" と表示されます。IL を見ると Where x = 0 と書いたのと同じような感じに解釈されているみたいです。
もちろん、Where x Is Nothing と書いた場合は意図どおり "1" という結果が表示されます。
どうやらここまで単純な場合だと "Is Nothing" と書いてやらないとダメなようです。

では、もうちょっと複雑なコード

    Dim ary() = { _
                    New With {.Name = "a", .Age = New Integer?(20)}, _
                    New With {.Name = "b", .Age = New Integer?(Nothing)} _
                }
    Dim query = From x In ary _
                Where x.Age = Nothing _
                Select x
    Console.WriteLine(query.Count())

おぉ、確かに "1" という結果が表示されます。この場合は "= Nothing" と書いても "Is Nothing" と同じように評価されているようです。
IL を見てみると "= Nothing" 部分は比較するコードは生成されておらず、代わりに Microsoft.VisualBasic.CompilerServices.Operators::ConditionalCompareObjectEqual() メソッドを呼び出すようになっています。この ConditionalCompareObjectEqual() メソッドの中までは調べていませんが、きっと Nullable と Nothing (null) との比較のときは HasValue をチェックするようになっているんでしょう。"= Nothing" と書いても "Is Nothing" と書いてもコンパイラは ConditionalCompareObjectEqual() メソッドを呼び出すコードを生成しています。なので、どちらの書き方をしても当然結果は同じになるわけです。


では、なぜ ConditionalCompareObjectEqual() メソッドが呼び出されるようになるんでしょうか?
それはきっと型が特定できないために late binding しているからでしょう。
ary の型を指定していないので object になっています。そして、そこから取り出した x も object です。Where の条件式 "x.Age = Nothing" の部分はラムダ式として解釈されているわけですが、そのメソッドの型を見ると bool Lambda(object) となっています。引数の object が x ですね。x が object なので x.Age というアクセスもできません (object には Age プロパティなんて無い)。そのため Microsoft.VisualBasic.CompilerServices.NewLateBinding::LateGet() メソッドを呼び出して Age にアクセスしています。そして ConditionalCompareObjectEqual() メソッドを呼び出して null と同じかどうかを判定しているわけです。
もちろん、こんなことになるのは Option Strict が Off の場合だけです。そもそも Option Strict On の場合はあちこちがコンパイルエラーになってしまいます。


では Option Strict On でも通るコード、すなわち late binding しないコードではどうなるでしょうか?


    Public Class Person
        Public Name As String
        Public Age As Nullable(Of Integer)
    End Class
 
    Sub Main()
        Dim ary As Person() = { _
                        New Person With {.Name = "a", .Age = 20}, _
                        New Person With {.Name = "b", .Age = Nothing} _
                    }
        Dim query = From x In ary _
                    Where x.Age = Nothing _
                    Select x
        Console.WriteLine(query.Count())
    End Sub

まぁ、答えは明らかなんですが、当然意図したようには動きません。この場合はきちんと "Is Nothing" としてやる必要があります。
(あれ?query の型は?と思ったらちゃんと IEnumerable(Of Person) と表示される。。。ひょっとして VB の Dim って C# の var の役割も兼ねてるの?)

2007年8月2日木曜日

Silverlight 1.0 RC2 がリリース?

Silverlight RC2 On The Way - We're Getting CLose! より

先週末に Silverlight 1.0 RC1 がリリースされたばかりですが、早くも RC2 がリリースされるようです。
上記の記事には "in the next couple of hours" とあるんですが 「2時間のうちに」 ということだったらすでに RC2 がリリースされてるのかな?"The update is Sunday night's drop." とあるので 7/29(日) の夜にビルドしたもの?
ちなみに RC1 が build 20724 で RC2 が build 20730 だそうです。

ただ、RC2 と言っても、RC1 からの breaking change は 1つも無いし、Silverlight.js や他のコードなども変更する必要はない、とのことです。

と言うか、上記記事の最後の段落に 「はっきり言うと、セキュリティ的な問題を見つけたからこのアップデートを出すわけではなくて、update broadcast system の public test のため」 みたいなことが書かれています。あと Silverlight 1.0 をリリースするまでおよそ 1週間おきくらいにあと何回かする予定、みたいなことも。ということで、そういうことなんでしょう。

2007年8月1日水曜日

Silverlight 1.0 SDK RC1 と 1.1 SDK Alpha Refresh

http://silverlight.net/GetStarted/
こちらに SDK なども一通りまとめられていますが、これらを入れてみました。

■ Silverlight 1.0 SDK RC1
前回までは単なる ZIP でしたけど、今回はちゃんと MSI になってますね。
ダウンロードしてダブルクリックすれば簡単に入れられます。この SDK にはドキュメントと QuickStarts などが含まれています。

また、セットアップ時に Visual Studio 2005 用のテンプレートも入れてくれます。
これで、Visual Studio 2005 でプロジェクトの新規作成をすると 「Silverlihgt Javascript Application」 を選択できるようになります。
もちろん、1.0 ですから mini-CLR ではなく JavaScript ですし、VS2005 ですから XAML をデザインできるわけではありませんけど。

ちなみに、Silverlihgt.js の Silverlight.createObject() に指定するバージョンですが、beta までは "0.9" でしたが RC1 からは "1.0" となったようです。

■ Silverlight 1.1 SDK Alpha Refresh
こちらはまだ ZIP のままです。ただ 1.0 SDK RC1 が 20MByte 程度なのに対して 1.1 SDK は 200MByte くらいあります。なんでこんなにサイズが違うのかと思ったら QuickStarts などで使っている画像なんかがでかいみたいです(笑)
1.0 SDK と同じくドキュメントと QuickStarts がメインです。Tools フォルダの下に SilverlightControlsStarterKit が入っていますが、内容は前回の SDK とあまり変わっていないようです。

1.1 SDK Alpha Refresh とは別にダウンロードできる 「Microsoft Silverlight Tools Alpha Refresh for Visual Studio (July 2007)」 を入れると Visual Studio 2008 にテンプレートが追加されます。これを入れるとプロジェクトの新規作成に 「Silverlight Project」 と 「Silverlight Class Library」 が追加されるようです。

Silverlihgt.js の Silverlight.createObject() に指定するバージョンは、"0.95" から "1.1" に変わったようです。
1.1 SDK Alpha Refresh に入っている QuickStarts などのサンプルを見ていると一部 "0.95" のままになっているものがあるようです。当然 "0.95" のままだと動きませんので注意。