.NET のジェネリック型パラメーターは、それ自体が型でなければなりません。ジェネリック型パラメーターの特定の値のみに固有のジェネリック型/メソッドを作成することはできません。
メソッドを制限したい属性値を表す型を作成したくない、または作成できない場合は、メソッドでサニティ チェックを実行して、提供された「foo」オブジェクトで適切な属性値が使用されていることを確認する必要があります。
特定の属性値の表現として特定の型を使用することは、あなたが尋ねた問題に対する答えかもしれませんが、switch-case ステートメントをサポートしないという欠点があります (以下を参照)。私の回答の最後にある最後のメモも読んでください。
たとえば、テクスチャを表す型が必要だとします。テクスチャは、さまざまな数のチャネルとさまざまなビット深度を持つことができます。次に、次のような一般的なテクスチャ タイプを宣言できます。
class Texture<TChannels, TBPC>
where TChannels : INumOfChannels,new()
where TBPC : IBitsPerChannel,new()
INumOfChannelsとIBitsPerChannelは単なるインターフェイスであり、空にすることができます。new()制約は、インターフェイス自体を使用して具体的な Texture タイプを作成することを防ぎます
。
さまざまなチャネルとさまざまな BPC に対して、それぞれの基本インターフェイスから拡張された空の型を作成します。次に例を示します。
class FourChannels : INumOfChannels {};
class ThreeChannels : INumOfChannels {};
class BitsPerChannel_24 : IBitsPerChannel {};
class BitsPerChannel_32 : IBitsPerChannel {};
これを使用すると、ジェネリック メソッドを特定の属性の組み合わせに制限できます。メソッドが 4 チャンネルおよび 32bpc テクスチャのみを処理する必要がある場合:
void MyMethod<TChannels, TBPC>(Texture<TChannels, TBPC> foo)
where TChannels : FourChannels
where TBPC : BitsPerChannel_32
さて、すべての良いものには暗い面もあります。このようなことをどのように行いますか (疑似コードとして記述)?
switch (NumOfChannelsAttribute)
{
case FourChannels:
// do something
break;
case ThreeChannels:
// do something else
break;
}
「FourChannel」と「ThreeChannel」は型であり、整数値ではないため、少なくとも簡単で単純な方法ではできません。
もちろん、if構文は引き続き使用できます。これが機能するためには、使用される属性を提供するジェネリック テクスチャ タイプにプロパティを実装する必要があります。
class Texture<TChannels, TBPC> where TChannels : INumOfChannels,new() where TBPC : IBitsPerChannel,new()
{
public Type ChannelsAttribute
{
get { return typeof(TChannels); }
}
public Type BitsPerChannelAttribute
{
get { return typeof(TBPC); }
}
}
ifコンストラクトでは、これを次のように利用できます。
var myTex = new Texture<FourChannels, BitsPerChannel_32>();
if (myTex.ChannelsAttribute == typeof(FourChannels))
{
... do something with 4 channels
}
else
{
... though luck, only 4 channels are supported...
}
最後の注意とアドバイス:
これで問題が解決する場合もありますが、この種の「トリック」に頼るのは通常、設計に欠陥があることを示しています。コードで行った設計上の選択を再検討するのは十分に投資された時間だと思うので、このような松葉杖に頼る必要はありません。