Amazon.co.jp: VisualC#2013パーフェクトマスター (Perfect Master SERIES): 金城 俊哉: 本
自分の不明点をとりまとめ。理解できているところは割愛。
配列とコレクション
1次元配列
int a = new int[10];
a[4] = 80;
二次元配列
int a = new int[3,10];
a[1,4] = 10;
コレクションクラス
ArratListクラスは動的に配列数を変更できる。
コレクションとは複数のオブジェクトをまとめて管理する機能。
ArrayList col = new ArrayList();
col.Add("hogehoge");
col.Add("fugafuga");
Console.WriteLine(col[1]);
ArrayListクラスのaddはobject型のためキャストが必要な場合がある
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ジェネリッククラスの方がパフォーマンス上優れている。
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クラス
キーと値をペアで管理します
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]);
}
}
型パラメータを持つクラス
同じ配列を繰り返し使える場合に型毎に配列を宣言せず、型パラメータを使って単一化できる。
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);
}
}
}
複数の型パラメータを持つクラス
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);
}
}
ジェネリック・メソッド
型パラメータをメソッドに対して設定してみる
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ステートメントを利用して簡略化が可能。
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でループするオブジェクトを事前に用意するのじゃなく、その都度メソッドで宣言できるということ?