本日は C# の技術調査枠です。
C#でdynamic型を使って動的な型チェックを検証した結果を記事にします。
dynamic型
dynamic型は静的な型チェックをバイパスします。
ほとんどの場合、object 型を使用する場合と同様に機能します。
dynamic型は C# 4 から導入されています。
docs.microsoft.com
サンプルコード
いくつかのサンプルコードを実行して dynamic 型の動きを確認してみます。
object型との違い
以下のコードで実行時の object 型と dynamic 型に代入した型を GetType() 関数で確認してみました。
dynamic dy = "abc"; object obj = "def"; Console.WriteLine("dy = {0}, type = {1}", dy, dy.GetType()); Console.WriteLine("obj = {0}, obj = {1}", obj, obj.GetType());
両方に string 型が代入されていることが分かります。
dynamic 型は実行時に型チェックが行われますが、object 型はコンパイル時に型チェックが行われます。
よって以下のコードは object 型ではコンパイルエラーが発生します。
dynamic dy = "abc"; object obj = "def"; string dyToText = dy; string objToText = obj;
dynamic 型はコンパイル時には dynamic 型としてあらゆる操作をサポートすると判定されています。
このため、コンパイルエラーは発生せず、実行時に型の整合性が取れていれば問題なく動作します。
dynamic dy = "abc"; string dyToText = dy; Console.WriteLine("dyToText = {0}, dyToText = {1}", dyToText, dyToText.GetType());
コレクションとの組み合わせ
例えば Dictionary 型と dynamic 型を組み合わせて以下のような多様な型を保持するコレクションを簡単に記述することができます。
Dictionary<string, dynamic> dict = new Dictionary<string, dynamic>(); dict["number"] = 123; dict["text"] = "123"; Console.WriteLine("dict_number = {0}, type = {1}", dict["number"], dict["number"].GetType()); Console.WriteLine("dict_text = {0}, type = {1}", dict["text"], dict["text"].GetType());
実行時のエラー
型に対する不正な操作は前述の通りコンパイル時にはエラーとして検出されず、実行時にエラーが発生します。
dynamic dy_text = "123"; dynamic dy_number = 123; Console.WriteLine("dy_text = {0}, type = {1}, Length = {2}", dy_text, dy_text.GetType(), dy_text.Length); // int型にLengthはないため、実行時にエラーになる Console.WriteLine("dy_number = {0}, type = {1}, Length = {2}", dy_number, dy_number.GetType(), dy_number.Length);