Genericsメソッドとparamsの優先順位

## 例えば
渡された配列なりListなりの中身を標準出力に全部出力するDebug用メソッドを用意したとして、とりあえずはこうなると思うんですよね

```csharp
    public static class DebugUtil
    {
        public static void ListDump<T>(IEnumerable<T> datas)
        {
            foreach (var data in datas)
            {
                Console.WriteLine(data);
            }
        }
    }
```

引数を`IEnumerable<T>`にしておけば

```csharp
        static void Main(string[] args)
        {
            var data = new[] {1, 2, 3, 4, 5};

            var list = new List<string>();
            list.Add("Hello");
            list.Add("Nice");
            list.Add("Too");
            list.Add("Meet");
            list.Add("You");

            DebugUtil.ListDump(data);
            DebugUtil.ListDump(list);
        }
```
配列でもListでも対応できるって寸法です。

ここで辞めておけばよかったんですが、さらに欲をかいて**可変長引数対応**もしたいな、ってなるわけです。
ちょっと追加してこんな感じ

```csharp
    public static class DebugUtil
    {
        public static void ListDump<T>(params T[] datas)
        {
            ListDump((IEnumerable<T>)datas);//キャストすることで、もう一つのListDumpを呼び出し
        }

        public static void ListDump<T>(IEnumerable<T> datas)
        {
            foreach (var data in datas)
            {
                Console.WriteLine(data);
            }
        }
    }
```

こうしておけば

```csharp
            DebugUtil.ListDump("ほげ","ふが");
```
みたいな感じ可変長引数も対応！　便利！


## んなこたない
ところが、これには罠が。

```csharp
        static void Main(string[] args)
        {
            var data = new[] {1, 2, 3, 4, 5};

            var list = new List<string>();
            list.Add("Hello");
            list.Add("Nice");
            list.Add("Too");
            list.Add("Meet");
            list.Add("You");

            DebugUtil.ListDump(data);//OK
            DebugUtil.ListDump(list);//NG
            DebugUtil.ListDump("ほげ","ふが");//OK
        }
```

この`DebugUtil.ListDump(list);`は
>System.Collections.Generic.List`1[System.String]

と出力されてしまうようになってしまいました。

## 問題はオーバーロードされたメソッドの処理順
まぁ、当たり前っちゃぁ当たり前なのかもですが、`params T[]`を引数に取るListDumpの方が先に処理されちゃったわけです。

すると、`T=List<string>` という事になり、`List<string>の配列` がdatasに入った形に。
ぐぬぬー。

というわけで、目的通りの処理にするためには

```csharp
DebugUtil.ListDump((IEnumerable<string>)list);
```
のように、明示的にキャストしてあげる必要がある。というわけでした。

めでたし・めでたくもなし。

## おまけ
Genericsを辞めて、

```csharp
    public static class DebugUtil
    {
        public static void ListDump(params object[] datas)
        {
            ListDump((IEnumerable) datas);
        }

        public static void ListDump(IEnumerable datas)
        {
            foreach (var data in datas)
            {
                Console.WriteLine(data);
            }
        }
    }
```
こんな感じで作ると、また挙動が変わって、`DebugUtil.ListDump(list);`は`ListDump(IEnumerable datas)`に処理されるので思った通りの挙動になったりします。

これは`object`へのキャストよりも`IEnumrable`へのアップキャストの方が階層が浅い（って言っていいのかな？）からだと思われます。

## おまけのおまけ
```csharp
    public static class DebugUtil
    {
        public static void ListDump(params object[] datas)
        {
            if (datas.Length == 0) return;
            if (datas.Length == 1)
            {
                var data = datas[0] as ICollection;
                if (data != null)
                {
                    ListDump(data);
                    return;
                }
                Console.WriteLine(datas[0]);
                return;
            }

            ListDump((IEnumerable) datas);
        }

        public static void ListDump(IEnumerable datas)
        {
            foreach (var data in datas)
            {
                ListDump(data);
            }
        }
    }
```

さらに、なんとなく適当に作ってみましたが、こんな感じで再起で行ったり来たりすると、配列の配列の配列のList みたいな変態的な構造も中身が全部表示される…かも。（あまりテストしてないです）
にしたって、もうちょっとマシな方法があるはず・・・。