{{indexmenu_n>21}}
====== generics ======
genericsはC++のテンプレートと同じようなものです。テンプレートの場合、型の解決は実際のコード中でそのテンプレートが利用されるときに行われますが、genericsではgenericを使ったクラスがあった場合、そのクラスを使うコードがなくてもコンパイルできなければなりません。実行時に動的にそのgenericsを利用可能にするためです。そのため以下のような問題があります。
以下のようなC++のテンプレートを考えます。
class C {
public:
int func() {
return 1;
}
};
template class Caller {
public:
int DoFunc(T& t) {
return t.func();
}
};
int main()
{
C c;
Caller caller;
int i = caller.DoFunc(c);
return 0;
}
これをC++/CLIのgenericsを使って書くと以下のようになり、コンパイルエラーとなります。
ref class C {
public:
int func() {
return 1;
}
};
generic ref class Caller {
public:
int DoFunc(T t) {
return t->func(); // error
}
};
int main()
{
C^ c = gcnew C;
Caller^ caller = gcnew Caller;
int i = caller->DoFunc(c);
return 0;
}
型Tはコンパイル時に解決しないため、Object型としかみなせないためです。そのためgenericsでは以下のような方法を利用します。
interface class I {
int func();
};
ref class C : I {
public:
virtual int func() {
return 1;
}
};
generic where T : I ref class Caller {
public:
int DoFunc(T t) {
return t->func();
}
};
int main()
{
C^ c = gcnew C;
Caller^ caller = gcnew Caller;
int i = caller->DoFunc(c);
return 0;
}
インターフェースIを利用して、型Tに縛りをかけます。
その他の注意点として、genericの型はハンドルか値型でなければなりません。