.NETエンジニア・プログラマ向けの技術情報・業界ニュースをお届けします。

  1. FEnet.NETナビ
  2. .NETコラム
  3. プログラミング言語
  4. C#
  5. C#のリフレクションとは?|基本の使い方から紹介!

C#のリフレクションとは?|基本の使い方から紹介!

  • C#
  • プログラミング言語
公開日時:   更新日時:
C#のリフレクションとは?|基本の使い方から紹介!
この記事でわかること
    基本情報技術者試験の試験対策はこちら>>


    システム
    エンジニア
    C#のリフレクションってどのようなものですか?
    プロジェクト
    マネージャー
    プログラムを開発する時に、プログラムの中身を反映させる時に使うものです。

    リフレクションとは?

    リフレクション(reflection)という言葉はどのような意味なのでしょうか。reflectionは、「投影、反映」という意味で、プログラム開発においては、プログラムの中身を反映させたい時に使います。

    リフレクションはC#に限らず、Javaなどのオブジェクト指向言語で使用される言葉で、「クラスのメタ情報を取得する」と説明されます。具体的に言うと、リフレクションとはプログラムのクラスやそのメンバーの名前、フィールドの型などを知ることが出来る機能のことです。

    この記事ではC#のリフレクションの機能と、具体的な使い方について解説します。是非参考にしてください。

    C#のリフレクションの基本

    説明より、まず実例を見てマスターしましょう。以下がC#のリフレクションサンプルです。

    using System;
    using System.Reflection;

    namespace ConsoleApp1
    {
    class Human
    {
    String name;
    public Human(String n)
    {
    name = n;
    }
    public void Eat(String food)
    {
    Console.WriteLine(name + “は ” + food + ” を食べます。”);
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    Type h_type = Type.GetType(“ConsoleApp1.Human”);

    if (h_type != null)
    {
    MethodInfo w_m = h_type.GetMethod(“Eat”);

    if (w_m != null)
    {
    var h = Activator.CreateInstance(h_type, new string[] { “太郎” });
    w_m.Invoke(h, new String[] { “昼食” });
    }
    }
    }
    }
    }

    文字列で指定してクラスを実行する

    上記の例にあるMainメソッド内で、Type.GetTypeによりHumanクラスの情報を取得しています。ここでは、”ネームスペース.クラス名”で指定する必要があります。

    返り値がnullではなければHumanクラスが存在するので、次にGetMethodでEatというメソッドがあるかどうかを、GetMethodでチェックします。

    GetMethodの戻り値がnullでなければ、Eatメソッドがあることになります。そこでActivator.CreateInstanceでHumanクラスを生成します。この時コンストラクタに”太郎”というパラメータを与えています。

    そして生成したHumanクラスのインスタンスのEatメソッドを、Invokeで呼び出します。この時”昼食”と言うパラメータを渡しています。実行結果は以下になります。

    太郎は 昼食 を食べます。

    リフレクションは動作テストに役立つ

    上のようなリフレクションは何に役立つのでしょうか。普通にHumanクラスを生成してEatメソッドを呼べばいいのではないか、と思う人もいるのではないでしょうか。実は、リフレクションは動作テストに役立つのです。

    上のソースはHumanクラスに直接アクセスせずに、Humanクラスを生成してEatメソッドを実行しています。なので、文字列を入れ替えれば、他のクラスにも使用でき、使いまわすことが可能になります。これが動作テストを行うのに便利なのです。

    リフレクションは通常は使用しない

    何かバグがあった場合、ソースに直接デバッグ用のコードを書くと、後でそれを消し忘れて残ってしまうということが起こる可能性があります。しかし、リフレクションを使えば外部からノータッチで動作チェックができるのです。

    逆に言えば、リフレクションは特殊な使い方をするもので、プログラムの中で普通に使用をするのは控えた方がよいでしょう。リフレクションは、C#のデバッガで処理を追うことが出来なくなる弊害もあります。あくまでも動作チェックをするために、テストコードだけで使用しましょう。

    リフレクションはログ出力にも便利

    リフレクションという考え方は、ログを出力する時も便利です。まず上のC#のサンプルの先頭に「using System.Diagnostics;」を記述してください。そしてHumanクラスのEatメソッドを以下のように変えます。

    public void Eat(String food)
    {
    Program.LogDisp(this);
    Console.WriteLine(name + “は ” + food + ” を食べます。”);
    }

    そしてProgramクラスを以下のように変えます。

    class Program
    {
    public static void LogDisp(object o)
    {
    StackFrame sf = new StackFrame(1); // 1つ前のスタックを取得
    Console.WriteLine(o.GetType() + ” ” + sf.GetMethod());
    }
    static void Main(string[] args)
    {
    Human h = new Human(“花子”);
    h.Eat(“夕食”);
    }
    }

    元のソースをほとんど変更せずにクラス情報を取得できる

    上のC#のプログラムを実行すると、以下のように表示されます。

    ConsoleApp1.Human Void Eat(System.String)
    花子は 夕食 を食べます。

    HumanクラスにLogDispを1か所追加しましたが、クラスやメソッドの情報は外側のLogDispで取得し、表示しています。StackFrameによりLogDispを呼び、メソッド名を表示していることに注意してください。

    元のプログラムにログ出力を追加するだけで、実行時に多くの情報を取得できるので、リフレクションはデバッグにとても役立つことが分かります。

    リフレクションはプロパティのテストにも使える

    プロパティを持つクラスのテストでも、リフレクションは役立ちます。下記にある、C#のサンプルをご覧ください。

    using System;
    using System.Reflection;

    namespace ConsoleApp1
    {
    class ThreeValSum
    {
    public int Val1 { get; set; }
    public int Val2 { get; set; }
    public int Val3 { get; set; }

    public int Sum()
    {
    return Val1 + Val2 + Val3;
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    Type type = Type.GetType(“ConsoleApp1.ThreeValSum”);

    if (type!=null)
    {
    PropertyInfo[] pinfo_ary = type.GetProperties();
    int len = pinfo_ary.Length;
    Console.WriteLine(“プロパティの数は” + len);

    var tvs = Activator.CreateInstance(type, null);

    for (int i = 0; i < len; i++) { var ap = tvs.GetType().GetProperty(pinfo_ary[i].Name); ap.SetValue(tvs, i+1); Console.WriteLine(pinfo_ary[i].Name + "に" + i + "を代入"); } MethodInfo s_m = type.GetMethod("Sum"); var sum = s_m.Invoke(tvs, null); Console.WriteLine("合計は"+sum); } } } }

    リフレクションなら効率的にテストが可能

    上のソースのTheeValSumは、3つのint型のプロパティを持ち、Sumメソッドでその3つの値を合計して返します。Mainメソッドでは、TheeValSumの全てのプロパティの情報をGetPropertiesで配列として取得しています。

    TheeValSumをCreateInstanceで生成し、GetPropertyでプロパティの名前を指定して、SetValueで全てのプロパティに値を代入しています。最後にSumを呼び出して結果を表示します。実行結果は以下になります。

    プロパティの数は3
    Val1に0を代入
    Val2に1を代入
    Val3に2を代入
    合計は6

    システム
    エンジニア
    メソッドを書き換えることで、反映させることができるのですね。
    プロジェクト
    マネージャー
    動作テストをするにはなくてはならない機能ですので、覚えておくといいでしょう。

    リフレクションで効率良く動作テストをしよう

    C#のリフレクションを紹介しましたが、いかがでしたでしょうか。リフレクションを使えばテスト対象のクラスを修正せず、効率よく動作確認を行えます。是非リフレクションをマスターし、品質の高いC#のプログラムを作ってください。

    FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
    株式会社オープンアップシステムロゴ

    株式会社オープンアップシステムはこんな会社です

    秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
    数多くのエンジニアが集まります。

    秋葉原オフィスイメージ
    • スマホアプリから業務系システムまで

      スマホアプリから業務系システムまで

      スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。

    • 充実した研修制度

      充実した研修制度

      毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。

    • 資格取得を応援

      資格取得を応援

      スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。

    • 東証プライム上場企業グループ

      東証プライム上場企業グループ

      オープンアップシステムは東証プライム上場「株式会社夢真ビーネックスグループ」のグループ企業です。

      安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。

    株式会社オープンアップシステムに興味を持った方へ

    株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。

    年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
    まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。

    株式会社オープンアップシステムへのご応募はこちら↓
    株式会社オープンアップシステムへのご応募はこちら↓

    C#新着案件New Job