読者です 読者をやめる 読者になる 読者になる

いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

.NET クラスライブラリ探訪-066 (Caller Information, CallerFilePath, CallerLineNumber, CallerMemberName, C# 5.0, 呼び元情報の取得)

C#


今回は、C# 5.0から追加された機能であるCaller Informationについてです。


Caller Information機能は、名前が示すとおり「呼び元の情報」を取得するための機能です。
__FILE__や__LINE__などと同じような機能がC#にも追加されたイメージです。


利用するにはメソッドの引数に特別な属性を指定します。
以下の属性を指定することで、呼び元のファイルパス、行番号、メンバー名が取得できます。

  • CallerFilePath
  • CallerLineNumber
  • CallerMemberName


以下のようにします。

using System.Runtime.CompilerServices;

void ShowCallerInfo([CallerFilePath] string file = "", [CallerLineNumber] int line = 0, [CallerMemberName] string member = "")
{
  ......
}


Caller Informationは、コンパイル時に解決されます。


以下サンプルです。

namespace Sazare.Samples
{
  using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Linq;
  using System.Runtime.CompilerServices;

  /// <summary>
  /// Caller Information (呼び元情報)についてのサンプルです。
  /// </summary>
  /// <remarks>
  /// C# 5.0にて追加された Caller Information属性についてのサンプルです。
  /// 以下の3つの属性について記述しています。
  /// 
  /// -CallerFilePath
  /// -CallerLineNumber
  /// -CallerMemberName
  /// </remarks>
  public class CallerInformationSamples01 : IExecutable
  {
    public void Execute()
    {
      //
      // Caller Informationは、C# 5.0にて追加された機能である。
      // Cの__FILE__や__LINE__と同じ要領で利用できる属性。
      // 追加された属性は以下の3つ。
      //   CallerFilePath:   ファイルパス
      //   CallerLineNumber: 行番号
      //   CallerMemberName: メンバー名
      // 上記の属性はメソッドの引数に指定して利用する.
      //
      // 注意点として、以下の点が存在する。
      //   ・引数にデフォルト値を指定していないとダメ
      //   ・コンパイル時に解決される情報である
      //
      // コンストラクタやデストラクタなどの一部のメソッドは
      // 特殊な名称が設定される。(.ctor, .cctor, Finalize)
      // 詳細については
      //   http://msdn.microsoft.com/en-us/library/hh534540.aspx
      // を参照の事。
      //
      // 利用する場合、以下の名前空間をインポートしておくこと。
      //   System.Runtime.CompilerServices
      //
      var manager = new CallerInfoManager();

      //
      // 各呼び出し時の呼び元情報を取得して表示.
      //
      Console.WriteLine(manager.Snap());
      Console.WriteLine(MethodA(manager));
      Console.WriteLine(MethodB(manager));
    }

    CallerInfoManager MethodA(CallerInfoManager manager)
    {
      return manager.Snap();
    }

    CallerInfoManager MethodB(CallerInfoManager manager)
    {
      return manager.Snap();
    }
  }

  /// <summary>
  /// Caller Informationを管理するクラス.
  /// </summary>
  class CallerInfoManager
  {
    /// <summary>
    /// ファイルパス
    /// </summary>
    public string FilePath   { get; private set; }
    /// <summary>
    /// 行番号
    /// </summary>
    public int    LineNumber { get; private set; }
    /// <summary>
    /// メンバー名
    /// </summary>
    public string MemberName { get; private set; }

    /// <summary>
    /// 現在のコンテキストでのCaller Informationをスナップします。
    /// </summary>
    /// <param name="file">ファイルパス</param>
    /// <param name="line">行番号</param>
    /// <param name="member">メンバー名</param>
    /// <returns>自分自身 (レシーバ)</returns>
    public CallerInfoManager Snap([CallerFilePath] string file = "", [CallerLineNumber] int line = 0, [CallerMemberName] string member = "")
    {
      FilePath   = file;
      LineNumber = line;
      MemberName = member;

      return this;
    }

    public override string ToString()
    {
      return string.Format("File:{0}\nLine:{1}\nMember:{2}", Path.GetFileName(FilePath), LineNumber, MemberName);
    }
  }
}


実行すると以下のようになります。

File:CallerInformationSamples01.cs
Line:51
Member:Execute
File:CallerInformationSamples01.cs
Line:58
Member:MethodA
File:CallerInformationSamples01.cs
Line:63
Member:MethodB


以下、参考資料です。


================================
過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。