【C#】配列やListなどの中身(要素)を見る拡張メソッド Dump [⇒PCページへ]

2021年01月11日16:42  C# 写真あり


 今回はデバッグに便利な拡張メソッドを作ってみよう。

 C# では静的配列も List などのコレクション系も IEnumerable という interface が実装されている。

 このインターフェイスは、簡単な理解ではイテレータ(ループなどで順次要素を取り出す)機能みたいなものだが、お陰で1つの拡張メソッドを定義しておけば、簡単に型違いの配列や List などを扱える便利なものでもある(Java でも Iterator というものがあるが、プリミティブ型には使えないため、少し不便)。

 またこの IEnumerableLINQ と組み合わせると簡潔に書けることも多いため、覚えておくと色々便利だ。

 ここでは簡単だが、利用頻度も高い拡張メソッドを定義しておこう。



●配列や List (Collections) などの中身(要素)を見る Dump
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public static class Extensions //※名前は任意
{
/// <summary>
/// コレクションのダンプ
/// 2021/01/11 Fantom
/// http://fantom1x.blog130.fc2.com/blog-entry-391.html
/// </summary>
public static string Dump<T>(this IEnumerable<T> source)
{
return (source == null) ? "[]"
: ("[" + string.Join(", ", source.Select(e => e.ToString()).ToArray()) + "]");
}

/// <summary>
/// コレクションのダンプ(string.Format 付き)
/// 2021/01/11 Fantom
/// http://fantom1x.blog130.fc2.com/blog-entry-391.html
/// </summary>
public static string Dump<T>(this IEnumerable<T> source, string format)
{
return (source == null) ? "[]"
: ("[" + string.Join(", ", source.Select(e => string.Format(format, e)).ToArray()) + "]");
}
}

●メインコード例
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

var nums = Enumerable.Range(0, 20).ToArray(); //int[]
var list = new List<string>()
{
"hoge", "fuga", "piyo"
};

Console.WriteLine(nums.Dump());
Console.WriteLine(list.Dump());

//Format 付きテスト
var sqrt = Enumerable.Range(1, 10).Select(e => Math.Sqrt(e)); //IEnumerable<double>
Console.WriteLine(sqrt.Dump("{0:F3}")); //小数点3桁

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[hoge, fuga, piyo]
[1.000, 1.414, 1.732, 2.000, 2.236, 2.449, 2.646, 2.828, 3.000, 3.162]

 string format の引数を持つオーバーロードは float や double 等、浮動小数点の型で使うと便利だろう。

 一覧を囲む文字は "["~"]" で固定してしまってるが、必要ならオーバーロード作るのも良い。

 配列(Array) や IEnumerable<T> をそのまま使えるので、利用範囲は広いと思う。

 ちなみに、文字列配列を結合するのに string.Join を使っているが、LINQEnumerable.Aggregate を使う手もある。しかし、実装速度は劣るようだ。

//string.Join の代わりに Enumerable.Aggregate を使っても良いが、実行速度は遅い
source.Select(e => e.ToString()).Aggregate((s, e) => s + ", " + e)

 どちらか言うと、デバッグにしか使わないと思うが、あまり巨大な配列などではないなら、開発中は常に色々ダンプして、中身をチェックした方が不具合も見つけやすい。

 こういうちょっとしたものが、意外とデバッグを楽にしてくれたりするんだよね(笑)。





(関連記事)
【Unity】【C#】LINQとfor, ListとArray(配列)での実行速度を比較してみる
【C#】連想配列(Dictionary)を値 or キーでソート
【C#】2次元配列(ジャグ配列・多次元配列)のソート
【C#】多次元配列とジャグ配列(2次元配列)のサイズ(長さ)、相互変換など


関連記事
トラックバックURL

http://fantom1x.blog130.fc2.com/tb.php/391-6fdbd088

前の記事 次の記事