今さらながら .NET Framework 2.0 で搭載される Generics のことです。
といっても解説じゃありません(^^;
基本的には以下のような感じですね。
(以下に書いているコードは VS2005 CTP March 2004 では動きました)
private static void TestGenerics()
{ List<int> l = new List<int>();
l.Add(0);
l.Add(1);
l.Add(2);
l.Add(3);
// 普通に Count でループ
for (int i = 0; i < l.Count; ++i)
{ Console.WriteLine(l[i].ToString());
}
// もちろん foreach でもループできる
foreach (int n in l)
{ Console.WriteLine(n.ToString());
}
}
通常版では自動拡張する配列は ArrayList クラスでしたが、Generics 版は List クラスになってます(たぶん(^^; リファレンスに List が見つからないんですが)。といっても、Generic なだけで使い方は ArrayList とほとんど同じです。
ただ、ArrayList はほんとに単なる 「自動拡張する配列」 でしたが、List にはいろいろとメソッドが増えてます。たとえば、Find とか。で、おもしろいのは、この Find の引数って Inttelisense で 「Predicate match」 って出てくるんですよ。Predicate ってなにかと言うと、
public sealed delegate bool Predicate(T obj);
という Generic な delegate なんですね。
ついでに言うと、Find の戻り値は Nullable だそうです。なるほど、たとえ T が値型だったとしても、見つからなかったときに null が返せるように Nullable になってるわけですね。
で、Find を使ったコードはというと以下のような感じ。
private static void TestGenerics()
{ List<int> l = new List<int>();
l.Add(0);
l.Add(1);
l.Add(2);
l.Add(3);
// 0 か 2 のものを探して表示
Console.WriteLine(l.Find(IsZeroOrTwo).Value.ToString());
}
private static bool IsZeroOrTwo(int n)
{ return n == 0 || n == 2;
}
ここでは、static なメソッドである IsZeroOrTwo を delegate のコールバックメソッドとして使ってます。この場合 0 と 2 の 2つが見つかりますが、Find は最初に見つかったほうだけを返すので 0 だけが表示されます。
あぁ、そうそう、検索した結果見つからなくて null が返ってきたときのチェックを省略しちゃってますが、もちろん、ほんとはすべきです。
どうでしょ?すごくイイ!と思いませんか?(私は激しく思います。色を変えたくなるくらい)
ただ、C++ の STL を知らないと Predicate の考え方がわかりにくいかもしれませんね。
もう 1つ。List.FindAll もあります。これは見つかったやつをみんな返すっていうメソッドです。なので、戻り値は List です。引数は Find と同じ。
それと ForEach っていうメソッドもあります。これの引数は 「Action action」 です。Action も、
public sealed delegate void Action(T obj);
です。Predicate との違いは戻り値が void なところだけですね。
この FindAll と ForEach を使うと、
private static void TestGenerics()
{ List<int> l = new List<int>();
l.Add(0);
l.Add(1);
l.Add(2);
l.Add(3);
// 0 か 2 のものを探して表示
l.FindAll(IsZeroOrTwo).ForEach(WriteLine);
}
private static bool IsZeroOrTwo(int n)
{ return n == 0 || n == 2;
}
private static void WriteLine(int n)
{ Console.WriteLine(n.ToString());
}
こんな感じに書けます。
さらに...
delegate は Anonymous Method として書けるはずです。ということは...
private static void TestGenerics()
{ List<int> l = new List<int>();
l.Add(0);
l.Add(1);
l.Add(2);
l.Add(3);
l.FindAll(delegate(int n)
{ return n == 1 || n == 3;
}).ForEach(delegate(int n)
{ Console.WriteLine(n.ToString());
});
}
っていう書き方ができるんです。
イイ!イイ!イイ!激しくイイ!
こりゃ楽しいや。