ヘッダー
C# サンプル集
 

呼び出し元のメソッド名などの情報を取得する

2020/11/8

→ Visual Basic のサンプルに切り替える

 

 

呼び出し元のメソッド名を取得する

この例を実行するにはファイルの先頭の方に using System.Runtime.CompilerServices; の記述が必要です。

public void InvokeTest()
{
    this.Test();
}

public void Test([CallerMemberName] string callerMethodName = "")
{
    System.Diagnostics.Debug.WriteLine(callerMethodName + " から呼び出されました。");
}

実行すると「InvokeTest から呼び出されました。」と表示されます。→ Debug.WriteLineが表示される場所

参考:呼び出し元情報

  • コンストラクターやプロパティが呼び出し元の場合、通常フレームワークによって隠蔽されている名前を取得します。下記の表の通りです。たとえば、コンストラクターが呼び出し元の場合、「.ctor」という名前を取得します。プロパティのgetが呼び出し元の場合ではget_プロパティ名を取得します。
種類 取得する名前
メソッド メソッド名。
プロパティ get_プロパティ名 または set_プロパティ名。例:get_Enabled
コンストラクター .ctor
静的コンストラクター .cctor
デストラクター Finalize
演算子 op_演算子名。例:op_Addition

 

次の例のように、任意の引数を追加しても機能します。

public void InvokeTest()
{
    this.Add(2, 3);
}

public int Add(int x, int y, [CallerMemberName] string callerMethodName = "")
{
    System.Diagnostics.Debug.WriteLine(callerMethodName + " から呼び出されました。");
    return x + y;
}

実行すると「InvokeTest から呼び出されました。」と表示されます。→ Debug.WriteLineが表示される場所

 

これでもできます。

public void InvokeTest()
{
    this.Test();
}

public void Test()
{
    var caller = new System.Diagnostics.StackFrame(1, false);
    string callerMethodName = caller.GetMethod().Name;

    System.Diagnostics.Debug.WriteLine(callerMethodName + " から呼び出されました。");
}

実行すると「InvokeTest から呼び出されました。」と表示されます。→ Debug.WriteLineが表示される場所

  • StackFrameクラスのコンストラクターの第1引数を、2、3、4、・・・とすると、呼び出し元の呼び出し元、その呼び出し元・・・というように情報をさかのぼれます。
  • 直接の呼び出し元の情報を取得するだけなら最初の例の方が優れています。
  • コンストラクターやプロパティが呼び出し元の場合、通常フレームワークによって隠蔽されている名前を取得します。上掲の表を参照してください。   

 

 

呼び出し元のクラス名を取得する

public void InvokeTest()
{
    this.Test();
}

public void Test()
{
    var caller = new System.Diagnostics.StackFrame(1, false);
    string callerClassName = caller.GetMethod().DeclaringType.FullName;

    System.Diagnostics.Debug.WriteLine(callerClassName + " クラスから呼び出されました。");
}

実行すると、たとえば「ConsoleApp1.TestClass クラスから呼び出されました。」と表示されます。→ Debug.WriteLineが表示される場所

  • StackFrameクラスのコンストラクターの第1引数を、2、3、4、・・・とすると、呼び出し元の呼び出し元、その呼び出し元・・・というように情報をさかのぼれます。

 

 

呼び出し元のファイル名を取得する

この例を実行するにはファイルの先頭の方に using System.Runtime.CompilerServices; の記述が必要です。

public void InvokeTest()
{
    this.Test();
}

public void Test([CallerFilePath] string callerFilePath = "")
{
    System.Diagnostics.Debug.WriteLine(callerFilePath + " ファイルから呼び出されました。");
}

実行すると、たとえば「C:\Users\rucio\Source\Repos\ConsoleApp1\TestClass.cs ファイルから呼び出されました。」と表示されます。→ Debug.WriteLineが表示される場所

  • ファイル名は、コンパイル時点でアセンブリ(exeファイルやdllファイル)内に文字列として埋め込まれます。そのため、開発者のパソコンとは異なるパソコンで実行しても、コンパイル時点で開発者のパソコンに存在していたソースコードのファイル名を取得します。ユーザー名など機密情報を含むパスを埋め込まないように注意してください。

 

 

呼び出し元の行番号を取得する

次の例では、InvokeTest 内で this.Test と記述されている行の行番号をを出力します。

この例を実行するにはファイルの先頭の方に using System.Runtime.CompilerServices; の記述が必要です。

public void InvokeTest()
{
    this.Test();
}

public void Test([CallerLineNumber] int callerLineNumber = 0)
{
    System.Diagnostics.Debug.WriteLine(callerLineNumber.ToString() + " 行目から呼び出されました。");
}

実行すると、たとえば「11 行目から呼び出されました。」と表示されます。→ Debug.WriteLineが表示される場所

 

これでもできます。

public void InvokeTest()
{
    this.Test();
}

public void Test()
{
    var caller = new System.Diagnostics.StackFrame(1, true);
    int callerLineNumber = caller.GetFileLineNumber();

    System.Diagnostics.Debug.WriteLine(callerLineNumber.ToString() + " 行目から呼び出されました。");
}

実行すると、たとえば「11 行目から呼び出されました。」と表示されます。→ Debug.WriteLineが表示される場所

  • StackFrameクラスのコンストラクターの第1引数を、2、3、4、・・・とすると、呼び出し元の呼び出し元、その呼び出し元・・・というように情報をさかのぼれます。
  • C# 5.0(2012年リリース)以降の場合、CallerLineNumber属性を使用する上の例の方が優れています。この例を採用する理由はありません。
  • デバッグビルド時のみ行数を取得できます。リリースビルドの場合行数は常に 0 になります。

 

 

呼び出し元のファイル名と行番号を偽装する

次の例では、呼び出し元を偽装し、実際とは異なるファイル名と行番号を指定して出力します。

この例を実行するにはファイルの先頭の方に using System.Runtime.CompilerServices; の記述が必要です。

public void InvokeTest()
{
#line 123 "C:\\xxx\dummy.cs"
    this.Test();
#line default
}

public void Test([CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0)
{
    System.Diagnostics.Debug.WriteLine($"{callerFilePath}ファイルの{callerLineNumber}行目から呼び出されました。");
}

実行すると、「C:\xxx\dummy.csファイルの123行目から呼び出されました。」と表示されます。→ Debug.WriteLineが表示される場所

  • 偽装できるのはファイル名と行番号だけです。クラス名とメソッド名は偽装できません。
  • このような偽装は、フレームワークなどが自動生成するソースコードの中で、自動生成の基になった設定やソースコードを追跡可能にするのが主要な目的です。

 

 

参考:呼び出し元のファイル名とメソッド名と行番号を取得する

この例はC# 7.0(2017年)以降で実行できます。ファイルの先頭の方に using System.Runtime.CompilerServices; の記述が必要です。

public void InvokeTest()
{
    this.Test();
}

public void Test(
    [CallerMemberName] string callerMethodName = "",
    [CallerFilePath] string callerFilePath = "",
    [CallerLineNumber] int callerLineNumber = -1)
{
    System.Diagnostics.Debug.WriteLine($"{callerFilePath}ファイルの{callerMethodName}{callerLineNumber}行目から呼び出されました。");
}

実行すると、たとえば「C:\Users\rucio\Source\Repos\ConsoleApp1\TestClass.csファイルのInvokeTestの11行目から呼び出されました。」と表示されます。→ Debug.WriteLineが表示される場所