|
|
連載:[完全版]究極のC#プログラミング
Chapter2 ジェネリック
川俣 晶
2009/08/17 |
|
|
2.6 ジェネリックメソッドと型推論
ジェネリックは、クラス以外にも使用できる。構造体やインターフェースにも使用できるだけでなく、デリゲートやメソッドにも使用できる。
ここでは、特にジェネリックを使用したメソッドである「ジェネリックメソッド」に注目しよう。これは、すぐに使える便利な機能であると同時に、注意を要する面もあるためだ。
クラスライブラリが提供するジェネリックメソッドの中で、特に誰でも使う可能性があるのは、配列をソートするArrayクラスのSortメソッドだろう。使い方はクラスと同様、メソッドの名前の後ろに「<」と「>」で囲んだ型名を書くだけである(リスト2.6参照)。なお、リスト2.6には、出力される内容をコメントとして記してある(以降も、記述を簡明にするため、必要に応じ同様の方法をとる)。
using System;
class Program
{
static void Main(string[] args)
{
int[] array = { 3, 2, 1 };
Array.Sort<int>(array); // ジェネリックメソッドの呼び出し
foreach (int i in array) Console.WriteLine(i);
// 出力:
// 1
// 2
// 3
}
}
|
|
リスト2.6 ジェネリックメソッドの使用例 |
<int>を指定したSort<int>メソッドは、引数にint型の配列を受け取り、その要素を昇順にソートするためのメソッドだ。
しかし、このArray.Sortの後ろにある<int>という記述はあまり意味がない。なぜなら、引数に指定した変数arrayの型がint[]型である以上、通常、<int>以外を記述することはありえないからだ。
そこで、「型の推論」という機能を使ってC#コンパイラに型を推理させることができる。この機能があるため、<int>を省いても意図どおりに動作する(リスト2.7参照)。
using System;
class Program
{
static void Main(string[] args)
{
int[] array = { 3, 2, 1 };
Array.Sort(array); // <int>を省略している
foreach (int i in array) Console.WriteLine(i);
// 出力:
// 1
// 2
// 3
}
}
|
|
リスト2.7 型の推論によってジェネリックメソッドを使う |
このコードは、一見しただけでは、C# 1.x時代のジェネリックメソッドでないSortメソッドの呼び出しと区別がつかない。しかし、ildasm*2や.NET Reflectorで実際に生成されたコードを見ると、ジェネリックではない従来版Sortメソッドではなく、型の推論が行われてSort<int>メソッドが呼び出されていることがわかるだろう。
さて、型の推論は強力ではあるが、まれに型の推論を使えない場合もある。
たとえば、異なるIComparableインターフェースを実装した基底クラスと派生クラスがある場合、それを明示的に使い分けなければ結果が変わってしまうことがある。実際にコーディングしたのが、次のリスト2.8である。
using System;
public class ClassA : IComparable<ClassA>
{
public int Value;
public ClassA(int v)
{
Value = v;
}
public int CompareTo(ClassA other)
{
return Value.CompareTo(other.Value);
}
}
public class ClassB : ClassA, IComparable<ClassB>
{
public ClassB(int v) : base (v) { }
public int CompareTo(ClassB other)
{
return other.Value.CompareTo(Value);
}
}
class Program
{
static void Main(string[] args)
{
ClassB[] array = {
new ClassB(3),
new ClassB(2),
new ClassB(1),
};
Array.Sort<ClassA>(array);
foreach (ClassB b in array) Console.WriteLine(b.Value);
// 出力:
// 1
// 2
// 3
Array.Sort<ClassB>(array);
foreach (ClassB b in array) Console.WriteLine(b.Value);
// 出力:
// 3
// 2
// 1
}
}
|
|
リスト2.8 型の推論が使えない例 |
このプログラムにおいて、型の指定を省略して「Array.Sort(array);」と記述すると「Array.Sort<ClassB>(array);」と推論されるが、その実行結果は「Array.Sort<ClassA>(array);」の実行結果とは異なるものになる。
*2 ildasmはマイクロソフトより提供される逆アセンブラ。Visual Studio等をインストールすると標準でインストールされる。
|
Insider.NET 記事ランキング
本日
月間