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

Anonymous Type, Implicitly typed arrays, Collection initializers

.NET

C# 3.0 の Anonymous Type かつ Implicitly typed arrays という組み合わせで,毎回フィールド名を書かされるのは面倒,という話.

var accessCounts = new[]
    {
        new { Month = new DateTime(2007, 1, 1), Total =25558, Unique = 18492},
        new { Month = new DateTime(2007, 2, 1), Total =24414, Unique = 18754},
        new { Month = new DateTime(2007, 3, 1), Total =29179, Unique = 22874},
        new { Month = new DateTime(2007, 4, 1), Total =25899, Unique = 20326},
        new { Month = new DateTime(2007, 5, 1), Total =22937, Unique = 18568},
        new { Month = new DateTime(2007, 6, 1), Total =26170, Unique = 20914},
        new { Month = new DateTime(2007, 7, 1), Total =29543, Unique = 23153},
        new { Month = new DateTime(2007, 8, 1), Total =33943, Unique = 26098},
        new { Month = new DateTime(2007, 9, 1), Total =25392, Unique = 19601},
        new { Month = new DateTime(2007, 10, 1), Total =33216, Unique = 25343},
        new { Month = new DateTime(2007, 11, 1), Total =39775, Unique = 29982},
        new { Month = new DateTime(2007, 12, 1), Total =36918, Unique = 27737},
    };

まあ確かにそうかも.とはいえこういうのはもはや手書きはしないよなぁとか,コード生成ルールを弄るのが正解かもという気もちらり,と.
とりあえず対応策.Add(DateTime month, int total, int unique) というメソッドを持ち,IEnumerable<T> を実装した型 X があれば,Collection initializers が使えるようになるのでもうちょっと簡単に書けるはず.というわけでいくつかヘルパークラスを書いてみました.
使い方はこんな感じ.

static class Program
{
    static void Main(string[] args)
    {
        var accessCounts = new TupleList<DateTime, int, int>
        {
            { new DateTime(2007, 1, 1), 25558, 18492},
            { new DateTime(2007, 2, 1), 24414, 18754},
            { new DateTime(2007, 3, 1), 29179, 22874},
            { new DateTime(2007, 4, 1), 25899, 20326},
            { new DateTime(2007, 5, 1), 22937, 18568},
            { new DateTime(2007, 6, 1), 26170, 20914},
            { new DateTime(2007, 7, 1), 29543, 23153},
            { new DateTime(2007, 8, 1), 33943, 26098},
            { new DateTime(2007, 9, 1), 25392, 19601},
            { new DateTime(2007, 10, 1), 33216, 25343},
            { new DateTime(2007, 11, 1), 39775, 29982},
            { new DateTime(2007, 12, 1), 36918, 27737},
        }.Select((Month, Total, Unique) => new { Month, Total, Unique });

        foreach (var item in accessCounts)
        {
            Console.WriteLine("{0} {1} {2}", item.Month, item.Total, item.Unique);
        }
    }
}

本体はこちら.

using System;
using System.Collections.Generic;

public partial struct Tuple<TArg1, TArg2>
{
    public readonly TArg1 Arg1;
    public readonly TArg2 Arg2;
    public Tuple(TArg1 arg1, TArg2 arg2)
    {
        this.Arg1 = arg1;
        this.Arg2 = arg2;
    }
}
public partial struct Tuple<TArg1, TArg2, TArg3>
{
    public readonly TArg1 Arg1;
    public readonly TArg2 Arg2;
    public readonly TArg3 Arg3;
    public Tuple(TArg1 arg1, TArg2 arg2, TArg3 arg3)
    {
        this.Arg1 = arg1;
        this.Arg2 = arg2;
        this.Arg3 = arg3;
    }
}
public partial struct Tuple<TArg1, TArg2, TArg3, TArg4>
{
    public readonly TArg1 Arg1;
    public readonly TArg2 Arg2;
    public readonly TArg3 Arg3;
    public readonly TArg4 Arg4;
    public Tuple(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
    {
        this.Arg1 = arg1;
        this.Arg2 = arg2;
        this.Arg3 = arg3;
        this.Arg4 = arg4;
    }
}

public sealed partial class TupleList<TArg1, TArg2> : List<Tuple<TArg1, TArg2>>
{
    public void Add(TArg1 arg1, TArg2 arg2)
    {
        this.Add(new Tuple<TArg1, TArg2>(arg1, arg2));
    }
    public IEnumerable<TResult> Select<TResult>(Func<TArg1, TArg2, TResult> selector)
    {
        return this.Select(item => selector(item.Arg1, item.Arg2));
    }
}

public sealed partial class TupleList<TArg1, TArg2, TArg3> : List<Tuple<TArg1, TArg2, TArg3>>
{
    public void Add(TArg1 arg1, TArg2 arg2, TArg3 arg3)
    {
        this.Add(new Tuple<TArg1, TArg2, TArg3>(arg1, arg2, arg3));
    }
    public IEnumerable<TResult> Select<TResult>(Func<TArg1, TArg2, TArg3, TResult> selector)
    {
        return this.Select(item => selector(item.Arg1, item.Arg2, item.Arg3));
    }
}

public sealed partial class TupleList<TArg1, TArg2, TArg3, TArg4> : List<Tuple<TArg1, TArg2, TArg3, TArg4>>
{
    public void Add(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
    {
        this.Add(new Tuple<TArg1, TArg2, TArg3, TArg4>(arg1, arg2, arg3, arg4));
    }
    public IEnumerable<TResult> Select<TResult>(Func<TArg1, TArg2, TArg3, TArg4, TResult> selector)
    {
        return this.Select(item => selector(item.Arg1, item.Arg2, item.Arg3, item.Arg4));
    }
}