Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

C#

C#のdynamic型とは?使いどころやvarとの違いもご紹介

投稿日:2021年6月10日 更新日:

 

<目次>

(1) C#のdynamic型とは?使いどころやvarとの違いもご紹介
 (1-1) dynamic型とは?
 (1-2) dynamic型の使いどころ
 (1-3) 動作確認サンプル①:動的に型を変更
 (1-4) 動作確認サンプル②:クラスのオブジェクトを割り当て
 (1-5) varとの違いは?

(1) C#のdynamic型とは?使いどころやvarとの違いもご紹介

(1-1) dynamic型とは?

dynamic型で定義された変数はコンパイル時(compile time)の型のチェックを回避し、実行時(runtime)する事が出来ます。内部的には、コンパイラがdynamic型をobject型に変換し、実際の型は実行時に決定される、という流れです。

目次にもどる

(1-2) dynamic型の使いどころ

dynamic型は変数のデータ型が1つに確定しない場合に役に立ちます。具体的な用途の例は以下のようなシーンが想定されます。

・①DOMのAPI(※注1)から返却されるオブジェクトを受け取る時
・②COM(※注2)から返却されるオブジェクトを受け取る時
 
(※注1)DOMとは?
Document Object Modelの略で、HTMLやXMLを「オブジェクト」として捉えてJavaScript等からアクセスするためのインターフェイス(API)です。具体的には画面をwindowやdocumentといった単位に見立て、各要素(テキストボックス、プルダウン、ラジオボタンなど)にアクセスしていきます。
 
(※注2)COMとは?
ソフトウェア部品(例:コンパイルされたバイナリのライブラリ)の「再利用」を可能にした技術です。COMの登場以前はクライアント側のコンポーネントがあるライブラリ(例:C++のライブラリ)を使用しようと思った場合に、そのライブラリをセットでのコンパイルが必要でした(これをしないとバイナリ内のメソッドやファンクションを特定できず、呼び出しができない)。
 
しかし、COMを使う事でそれらのメソッド群を構造化し、その構造のデータを保持する独立したファイル(IDL)が作られます。クライアント側では、このIDLの内容をOSのレジストリに登録する事によって、クライアントのアプリはそのレジストリの情報を参照し、ライブラリのメソッドの呼び出す事が可能になります。

目次にもどる

(1-3) 動作確認サンプル①:動的に型を変更

dynamic型の変数に様々な型の値を代入していき、代入する度に変化していく様子が確認しています。

(サンプル)
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestProject
{
    class DynamicTypeTest1
    {
        public void Test()
        {
            Console.WriteLine("##### DYNAMIC TYPE TEST#1 START #####");

            //# int型で設定
            dynamic testvalue = 10;
            Console.WriteLine("値: {0}, 型: {1}", testvalue, testvalue.GetType());
           
            //# string型に変更
            testvalue = "This is an Apple";
            Console.WriteLine("値: {0}, 型: {1}", testvalue, testvalue.GetType());

            //# bool型に変更
            testvalue = false;
            Console.WriteLine("値: {0}, 型: {1}", testvalue, testvalue.GetType());

            //# long型に変更
            testvalue = 1L;
            Console.WriteLine("値: {0}, 型: {1}", testvalue, testvalue.GetType());

            //# double型に変更
            testvalue = 0.005;
            Console.WriteLine("値: {0}, 型: {1}", testvalue, testvalue.GetType());

            Console.WriteLine("##### DYNAMIC TYPE TEST#1  END  #####");
        }
    }
}
(図131)
 
あとは、このTestメソッドをmain文から呼び出して結果を確認します。
(図132)

 

(実行結果)
型が値を代入する度に変化していく様子が確認できます。
 
##### DYNAMIC TYPE TEST#1 START #####
値: 10, 型: System.Int32
値: This is an Apple, 型: System.String
値: False, 型: System.Boolean
値: 1, 型: System.Int64
値: 0.005, 型: System.Double
##### DYNAMIC TYPE TEST#1  END  #####

 

(図133)

 

目次にもどる

(1-4) 動作確認サンプル②:クラスのオブジェクトを割り当て

次にdynamic型の変数に、カスタムクラス(例:Fruit)のオブジェクトを割り当てる例をご紹介します。

前半の(パート#1)ではdynamicを使わずに通常の書き方(Fruit型の変数にFruit型オブジェクトを割り当てる)をしており、メソッドに不正な引数を与えると、当然ながらコンパイルエラーになっています。

後半の(パート#2)ではdynamic型にFruit型のオブジェクトを割り当てており、同様にメソッドに不正な引数を与えていますが、コンパイル時点ではエラーになっていません。

(図141)

コンパイルエラーの部分(24行目)をコメントアウトして実行すると、dynamicの特性として実行時(ランタイム)にエラーを検知するので、実行時に不正な引数のためエラーになります。

(図142)

(サンプル)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TestProject.Models;

namespace TestProject
{
    class DynamicTypeTest2
    {
        public void Test()
        {
            Console.WriteLine("##### DYNAMIC TYPE TEST#2 START #####");

            //# (パート#1)通常の書き方

            //# Fruit型にFruitクラスのオブジェクトを割り当て
            Fruit fr1 = new Fruit();
            fr1.Id = "A001";
            fr1.Name = "Apple";
            fr1.Price = 200;
            fr1.Origin = "青森";
            //fr1.AddPrice("Dummy1", "Dummy2");

            ////# (パート#2)dynamic型を使った書き方

            //# dynamic型にFruitクラスのオブジェクトを割り当て
            dynamic fr2 = new Fruit();
            fr2.Id = "A002";
            fr2.Name = "Banana";
            fr2.Price = 90;
            fr2.Origin = "インド";
            fr2.AddPrice("Dummy1", "Dummy2");

            Console.WriteLine("##### DYNAMIC TYPE TEST#2  END  #####");

        }
    }
}

 

あとは、テストに使用したMainメソッドはFruitモデルについては以下のように記述しました。
 
(図143)Mainメソッド

(サンプル)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestProject
{
    class Home
    {
        static void Main(string[] args)
        {
            DynamicTypeTest2 dt2 = new DynamicTypeTest2();
            dt2.Test();

        }
    }
}
 
(図144)Fruitモデル
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TestProject.Models
{
    public class Fruit
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public double Price { get; set; }
        public string Origin { get; set; }
        public DateTime HarvestDate { get; set; }

        public double AddPrice(int Price)
        {
            double prc = Price;
            prc = prc * 1.1;
            return prc;
        }
    }
}

プログラム全体の構造は次のようになっています。

 
(図145)

(1-5) varとの違いは?

varとdynamicの違いを表に整理しました。

(表)

■項目 ■var ■dynamic
導入時期 C#3.0 C#4.0
定義 varキーワードを使用 dynamicキーワードを使用
特性
(dynamic/static)
staticに型を決定
(コンパイル時に判定)
dynamicに型を決定
(実行時に判定)
初期化のタイミング 定義時の初期化は「必須」
(コンパイラが判断できるよう)
定義時の初期化は「任意」
(コンパイル時に型が確定しない為)
戻り値での使用可否 NG
(function内のローカル変数としてのみ使用可能)
OK
 

Adsense審査用広告コード


Adsense審査用広告コード


-C#

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

C#で文字列をタブやスペースで区切り配列に格納する方法

<目次> (1) C#で文字列をタブやスペースで区切り配列に格納する方法  (1-1) 基本構文  (1-2) 基本構文サンプルプログラム  (1-3) 応用構文  (1-4) 応用構文サンプルプログ …

C#のlockとは?意味や使い方とサンプルプログラムをご紹介

  <目次> (1) C#のlockとは?意味や使い方とサンプルプログラムをご紹介  (1-1) 概要  (1-2) 構文  (1-3) サンプルプログラム  (1-4) lockステートメ …

Visual Studioのプロジェクトを別ソリューションに移動する手順

  <目次> (1) Visual Studioのプロジェクトを別ソリューションに移動する手順  (1-1) プロジェクトを別ソリューションに移動する手順  (1-2) 参考①:「.cspr …

C#で配列に特定の値があるか?をチェックする方法を2つご紹介~ContainsとLINQ~

<目次> (1) C#で配列に特定の値があるか?をチェックする方法  (1-1) 方法①:ListクラスのContainsメソッドを使う方法   (1-1-1) 構文   (1-1-2) サンプルプロ …

ASP.NETのActionResultの戻り値の種類について

  <目次> (1) ASP.NETのActionResultの戻り値の種類について  (1-1) はじめに  (1-2) ASP.NETのActionResultの戻り値の種類  (1-3 …

  • English (United States)
  • 日本語
Top