MRが楽しい

MRやVRについて学習したことを書き残す

C#でdynamic型を使って動的な型チェックを利用する

本日は 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());

f:id:bluebirdofoz:20211028231847j:plain

両方に string 型が代入されていることが分かります。
dynamic 型は実行時に型チェックが行われますが、object 型はコンパイル時に型チェックが行われます。
よって以下のコードは object 型ではコンパイルエラーが発生します。

dynamic dy = "abc";
object obj = "def";

string dyToText = dy;
string objToText = obj;

f:id:bluebirdofoz:20211028231858j:plain

dynamic 型はコンパイル時には dynamic 型としてあらゆる操作をサポートすると判定されています。
このため、コンパイルエラーは発生せず、実行時に型の整合性が取れていれば問題なく動作します。

dynamic dy = "abc";

string dyToText = dy;

Console.WriteLine("dyToText = {0}, dyToText = {1}", dyToText, dyToText.GetType());

f:id:bluebirdofoz:20211028232014j:plain

コレクションとの組み合わせ

例えば 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());

f:id:bluebirdofoz:20211028232024j:plain

実行時のエラー

型に対する不正な操作は前述の通りコンパイル時にはエラーとして検出されず、実行時にエラーが発生します。

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);

f:id:bluebirdofoz:20211028232040j:plain