今さら Caller Information

というのを知りました。C# 5 で入ったんですね。C# 6 が出ようとしているのに本当に今さらです。なんかすいません。脳に刻んでおくための自分用メモということで書き残しておきます。

参考

万が一「Caller Information って何!?」という人がいたら、以下のサイトを読まれるといいでしょう。

.NET クラスライブラリ探訪-066 (Caller Information, CallerFilePath, CallerLineNumber, CallerMemberName, C# 5.0, 呼び元情報の取得) - いろいろ備忘録日記
C# 5.0 の新機能 (C# によるプログラミング入門)
呼び出し元情報 (C# および Visual Basic)

検証コード

class Program
{
    static void Main(string[] args)
    {
        WriteLog("Call WriteLog()");
        new Action(() => WriteLog("Call WriteLog() in Action"))();
        Hoge(() => WriteLog("Call WriteLog() in Hoge"));
        Task.Run(async () =>
        {
            await HogeAsync();
            WriteLog("Call WriteLog in Anonymous");
        }).Wait();
    }
    static void WriteLog(
        string message,
        [CallerFilePath] string path = "",
        [CallerLineNumber] int lineNumber = 0,
        [CallerMemberName] string member = "")
    {
        Console.WriteLine(string.Join(", ", new[]{message, Path.GetFileName(path), lineNumber.ToString(), member}));
    }
    static async Task HogeAsync()
    {
        await Task.Delay(1);
    }
    static void Hoge(Action act)
    {
        act();
    }
}

実行結果

Call WriteLog(), Program.cs, 16, Main
Call WriteLog() in Action, Program.cs, 17, Main
Call WriteLog() in Hoge, Program.cs, 18, Main
Call WriteLog in Anonymous, Program.cs, 22, Main
続行するには何かキーを押してください . . .

使い道

ロガーのラッパークラスとかある場合は、ログ出力メソッドに片っ端から付けて回るのがいいんじゃないでしょうか。コンパイル時に文字列に展開されるそうなのでコードの最適化による影響とか実行時パフォーマンスの低下は考えなくて良さそうです。

それと、非同期処理のスタックトレースのぱっと見の分かりづらさを何とか出来ないかと考えましたが、いい方法が思いつきませんでした。非同期に限らずとも色々上手く組み合わせればもう少し面白いことが出来そうな気がするんですが。うーん。。。