このシナリオは、DirectCastが非オブジェクト(オブジェクトキーワード)型のセキュリティをチェックするコンパイル時型の誤った感覚を持っている理由を最もよく要約していると思います。
float f = 10;
long l = f;
Option Strict On
Dim f As Single = 10
Dim l As Long = f
AC#コーダーは、floatがlongに直接割り当てられず、コンパイルされないことを発見すると、次のことを行います。
long l = (long)f;
どちらが正しい。
ここで、VB.NETコーダーに目を向けましょう。フロートがロングに割り当てられず、コンパイルされないことがわかったら、これを試みます。
Dim l As Long = DirectCast(f, Long)
数秒後...
VB.NETプログラマー:「入札をさせてください、コンパイルしてください...!!!」
いくつかのグーグル-fuとMSDN-ブラウジングの瞬間の後:
VB.NETプログラマー:「ああ、変数をキャストするためにこのCLngまたはCType構造を使用する必要があります」
Dim l As Long = CLng(f)
これは、DirectCastがコンパイル時の型チェックのセキュリティについて誤った感覚を持っていることを意味していました。DirectCastは、プログラマーがいつどこで使用すべきかわからない場合にバックスペースを設定することを目的としています。DirectCastは、常に着用されているわけではないセキュリティブランケットです。
結局使用されない場合、このシナリオでDirectCastはどの程度役に立ちますか?
[編集]
@ジュール
すべてのVB.NETプログラマーがDirectCastの実際の使用法を知らないと言っているわけではありません。それらのいくつかは、DirectCastがオブジェクト型(およびオブジェクトでボックス化されたプリミティブ型)にのみ使用されることを意図していることを実際に知っています。
既存のC#コードをVB.NETに再コーディングするVB.NETコーダーが間違った結論に達する1つのシナリオは、予想される(正しいかどうかにかかわらず)言語の対称性です。
彼/彼女がコードで見るとき、この構成...
TextBox txt = (TextBox)sender;
...彼/彼女はそれをこれに翻訳します:
Dim txt As TextBox = DirectCast(sender, TextBox)
どちらが正しい。
さて、私たちプログラマーは対称性が大好きなので、私たちの何人か(CLngを知らなければ私もそうかもしれません)はこのコードを変換する傾向があります...
/* Numbers are stored in file as float(component's file structure
is designed by 3rd party company) */
float f = file.ReadFloat(0);
long l = (long)f; // But we don't care about using the fractional part
...これに:
Dim f As Single = file.ReadFloat(0)
Dim l As Long = DirectCast(f, Long)
C#の人がC#コードをVB.NETに変換する人である場合、ここでの対称性の明らかな欠如に不満を感じるでしょう。
しかし、C#コードをVB.NETに変換するタスクを課されたVB.NETの人にとって、C#コンパイラは互換性のない型の割り当てをキャッチしないが、VB.NETはそれをキャッチするという印象を受けます。さて、その明らかな発見のために、そのVB.NET機能を彼の同僚やいくつかのフォーラムに自慢します。
しかし、VB.NETプログラマーが、最初のコードの意図を誤って推測するという間違いを犯さないようにしてください。上記のC#のコードフラグメントは、最初は次のように記述されていたように、その寿命を開始しました。
float f = file.ReadFloat(0);
long l = f;
そして、それはコンパイルされません。C#コンパイラは、互換性のない型の割り当てをキャッチします。これは、同等のVB.NETでもコンパイルされないのと同じです(ただし、がに設定されているOption Strict On
場合にのみコンパイルされませんが、あまりにも寛大です)。したがって、を使用してfloatをlongに型キャストする必要があります。これになります:Option Strict
On
(long)
long l = (long)f;
ここで、このコードを変換するのと同じように、ある変数タイプを別の互換性のあるタイプにキャストします...
TextBox txt = (TextBox)sender;
...このコードに:
Dim txt As TextBox = DirectCast(sender, Textbox)
このコードを変換する必要があります...
long l = (long)f; // Will compile
...このコードに:
Dim l As Long = DirectCast(f, Long) ' Will not compile
しかし、残念ながら、それはコンパイルされません。互換性のあるプリミティブ型間のキャストでは、これがDirectCastの欠点です。上記のC#コードとの対称性はなく、Direct Castという名前にもかかわらず、互換性のあるプリミティブ型のキャストには使用できません。
私の見方では、DirectCastはCastObjectという名前にする必要があります。これは、とにかくオブジェクトタイプ(およびオブジェクトでボックス化されたプリミティブタイプ)間でのみキャストできるためです。DirectCastは、互換性のあるプリミティブ型(integer、double、およびそれらの下位と上位の対応物)を割り当てることには実際には関係ありません。互換性のあるプリミティブ型間で割り当てる場合、DirectCastは役に立たなくなります。特に、とにかくバックスペースを作成して、適切なものに置き換えます。
または、別の見方をすれば、DirectCast構造を修正して、C、C ++、C#、Java、Delphi、Dなど、新旧の言語と同じように互換性のある型をキャストできるようにする必要があります。型キャストに関しては、他の言語に対してVB.NETに大きな対称性を提供します。これを行うことで、名前がその型に直接マップされない多数の関数(CInt、CDbl、CSngなど)をすべて破棄することもできます(仮想的にのみ、古い関数に依存する他のプログラムを失敗させることはできません)。 。それらの代わりにDirectCastを使用します。