C#
.NET
拡張メソッド

【C#】変数のデバッグログ出力を簡単に行う拡張メソッド

More than 1 year has passed since last update.

拡張メソッド+Jsonシリアライザを利用したログ出力拡張メソッドを作ります。
デバッグログ出力のためにコードを汚したくない人におすすめです。

普通のデバッグ出力の場合

普段、変数の状態を出力する時は

using System.Diagnostics;

var index = 1;
Debug.WriteLine("index = {0}", index);

var array = new int[] { 1, 2, 3 };
Debug.WriteLine("array = [{0}]", string.Join(", ", array));

こんな感じに出力すると思います。
この程度ならちゃちゃっと書けば済む話ですが、クラスのフィールドやプロパティの状態を出力したい時は

using System.Diagnostics;

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public override string ToString()
    {
        return string.Format("Name = {0}, Age = {1}", Name, Age);
    }
}

var person = new Person() { Name = "hoge", Age = 20 };
Debug.WriteLine("person = {0}", person);

みたいにToStringをオーバーライドしていちいちログ出力のためのコードを書かなければいけません。
ちょっとしたプログラムならさほど面倒ではありませんが、クラスのプロパティを修正したり追加したりするたびにログ出力のためのコードも修正しなければならないので正直面倒です。

作るもの

こんな感じにデバッグログ出力できるものを作ります。

var index = 1;
index.DebugLog("index");

var array = new int[] { 1, 2, 3 };
array.DebugLog("array");

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

var person = new Person() { Name = "hoge", Age = 20 };
person.DebugLog("person");

これだけで

index = 1
array = [
  1,
  2,
  3
]
person = {
  "Name" : "hoge",
  "Age" : 20
}

このような変数名=Json形式で値を出力してくれる拡張メソッドを作ります。
変数の対象が数値、配列、クラスでもなんでも .DebugLog(name)をつけるだけでいいのでかなり楽です。
また、ToStringをオーバーライドしてうんたらかんたらもやらなくていいのでコードもすっきりします。

以下実装方法

準備

まず、http://www.newtonsoft.com/jsonからJsonシリアライザのDLLをダウンロードして、
Newtonsoft.Json.dllをプロジェクト参照に追加してください。
デバッグログ出力の形式は何でもいいのですが、ここではシンプルで見やすいJson形式で出力するために上記のdllを利用します。

Newtonsoft.Json.dllを参照できるようにしたら以下のクラスを作成し、拡張メソッドを記述します。
名前はログの拡張機能ということでLogExtensionにしています。

LogExtension.cs
using System;
using System.Diagnostics;
using Newtonsoft.Json;

static class LogExtension
{
    [Conditional("DEBUG")]
    public static void DebugLog<T>(this T obj, string name)
    {
        try
        {
            var json = JsonConvert.SerializeObject(obj, Formatting.Indented);
            Debug.WriteLine("{0} = {1}", name, json);
        }
        catch
        {
            Debug.WriteLine("{0} : Debug Log Error!", name);
        }
    }
}

これだけです。ものすごく簡単です。
引数のnameもどの変数が出力しているのかを確かめるためのものなので、あってもなくてもいいです。
もっといろいろ魔改造してさらに便利なログ出力機能を追加するのもいいですね。

ちなみに変数がnullの場合でもちゃんと変数名 = nullって出力してくれます。

System.Code.dllへの参照が~でエラーが出る場合

最近の.NetであればSystem.Codeが最初から参照されているので問題ないですが、.Net Framework3.0とかだと拡張メソッドを使うのにちょこっと工夫しなければいけません。といっても

ExtensionAttribute.cs
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
    sealed class ExtensionAttribute : Attribute { }
}

上記のクラスを定義するだけです。

まとめ

どんな型の変数でも.DebugLog()をつけるだけでデバッグログ出力をしてくれる拡張メソッドを作りました。
今回は楽するためにNewtonsoft.Json.dllを使ってJson形式で出力するようにしましたが、工夫すればもっとわかりやすいログにすることができるかもしれません。

拡張メソッド便利!