Visual C# 2013 パーフェクトマスター 6章 コレクションとジェネリック

[Amazon.co.jp： VisualC#2013ﾊﾟｰﾌｪｸﾄﾏｽﾀｰ (Perfect Master SERIES): 金城 俊哉: 本](http://www.amazon.co.jp/VisualC-2013%EF%BE%8A%EF%BE%9F%EF%BD%B0%EF%BE%8C%EF%BD%AA%EF%BD%B8%EF%BE%84%EF%BE%8F%EF%BD%BD%EF%BE%80%EF%BD%B0-Perfect-Master-SERIES/dp/4798040193)

自分の不明点をとりまとめ。理解できているところは割愛。

# 配列とコレクション
## 1次元配列
```csharp
    int a = new int[10];
    a[4] = 80;
```

## 二次元配列
```csharp
    int a = new int[3,10];
    a[1,4] = 10;
```

## コレクションクラス
ArratListクラスは動的に配列数を変更できる。
コレクションとは複数のオブジェクトをまとめて管理する機能。

```csharp
            ArrayList col = new ArrayList();
            col.Add("hogehoge");
            col.Add("fugafuga");
            Console.WriteLine(col[1]);
```

ArrayListクラスのaddはobject型のためキャストが必要な場合がある

```csharp
            ArrayList col = new ArrayList();
            col.Add(100);
            string text = "hogehoge";
            col[0] = text;
            text = col[0];
            /// 'object' を 'string' に暗黙的に変換できません。
            /// 明示的な変換が存在します。(cast が不足していないかどうかを確認してください)
            /// text = Convert.ToString(col[0]);
```

# ジェネリック
ジェネリックは様々な型に対応するために型をパラメータとして指定し、その型に対応したクラスやメソッドを生成する機能。

## Listジェネリッククラス
Listジェネリッククラスではパラメータリストにデータ型を記述することでリストで扱うデータ型が指定できる。
ArryListクラスではキャストが必要だったためListジェネリッククラスの方がパフォーマンス上優れている。

```csharp
            List<string> list = new List<string>();
            list.Add("100"); /// list.Add(100)ならエラー
            string text = "hogehoge";
            list[0] = text;
            text = list[0];
            Console.WriteLine(list[0]);
```

## Dictionaryクラス
キーと値をペアで管理します

```csharp
        static void Main(string[] args)
        {
            var obj = new Dictionary<string, int>();
            obj.Add("hogehoge", 10);
            obj.Add("fugafuga", 20);
            Disp(obj);
        }

        static void Disp(Dictionary<string, int> t)
        {
            foreach (var item in t.Keys)
            {
                Console.WriteLine(item, t[item]);
            }

        }
```

### 型パラメータを持つクラス
同じ配列を繰り返し使える場合に型毎に配列を宣言せず、型パラメータを使って単一化できる。

```csharp
namespace ConsoleApplication1
{

    public class ListTest<T>        /// Tは型パラメータ。コンストラクタで指定。
    {
        T[] list = new T[100];      /// Tの型の配列を100個宣言
        int add;                    /// 配列のインデックス値

        public void AddItem(T item) /// 配列格納用のメソッド
        {
            list[add++] = item;     /// add++で呼び出し毎に配列を追加して値を格納
        }

        public T this[int index]    /// インデクサ
        {
            get
            {
                return list[index]; /// indexを指定して呼び出し
            }
            set
            {
                list[index] = value;/// 値をセット
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ListTest<string> list = new ListTest<string>();

            list.AddItem("1番目");
            list.AddItem("2番目");

            string str1 = list[0];
            Console.WriteLine(str1);

            ListTest<DateTime> dtlist = new ListTest<DateTime>();

            dtlist.AddItem(DateTime.Today);

            DateTime today = dtlist[0];
            Console.WriteLine(today);
        }
    }
}
```

### 複数の型パラメータを持つクラス

```csharp
    class test<T1, T2>
    {
        public T1 val1 { get; set; }
        public T2 val2 { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var a = new test<string, int>();
            var b = new test<int, string>();

            a.val1 = "abc";
            a.val2 = 100;
            b.val1 = 200;
            b.val2 = "xyz";

            Console.WriteLine(a.val1 + "," + a.val2);
            Console.WriteLine(b.val1 + "," + b.val2);
        }
    }
```
　
### ジェネリック・メソッド
型パラメータをメソッドに対して設定してみる

```csharp
    class Program
    {
        static void Disp<T>(T p)
        {
            Console.WriteLine(p);
        }

        static void Main(string[] args)
        {
            Disp<int>(500);
            Disp<string>("hogehoge");

            Disp(500); /// 型指定は省略可
            Disp("fugafuga");
        }
    }
```

### 型パラメーターの命名ガイドライン
型パラメーターは1文字で指定。「T」
複数の型パラメーターを持つ場合はわかりやすく、先頭にTをつける。「TInput,TOutput」等。

# イテレーター
クラス内での繰り返し処理を行うforeachステートメントはコードが複雑かつ冗長になる場合がある。
yieldステートメントを利用して簡略化が可能。

```csharp
    class Program
    {
        public static IEnumerable MethodShow()
        {
            yield return "hogehoge";
            yield return "fugafuga";
            yield return "piyopiyo";
        }

        static void Main(string[] args)
        {
            foreach(string val in Program.MethodShow())
            {
                Console.WriteLine(val);
            }
        }
    }
```

# 疑問点
## イテレータ
「foreachステートメントはコードが複雑かつ冗長になる場合があるのでイテレーターのyieldステートメントを使う」とあるが、サンプルコードを見る限りforeach文自体はあまり簡略化されてない気がする。
foreachでループするオブジェクトを事前に用意するのじゃなく、その都度メソッドで宣言できるということ？