2012-04-04 15 views
7

私は必要なものに対して洗練されたソリューションを持っていますが、それを置き換えるための洗練されたソリューションを探しています。C#で一般的に継承される型の制限

次のコードはコンパイルが、私がやりたいものを表していません:

interface IWebService 
{ 
} 

abstract class BaseClient<T> 
{ 
} 

class SpecializedClient : BaseClient<IWebService> 
{ 
} 

class ClientHelper<T> where T : BaseClient<*> 
{ 
} 

ClientHelper<T>Tにかかわらず、渡されたテンプレートタイプのBaseClientを拡張するすべてのクラスである場合は

。私が見つけた

無粋ソリューションは以下のとおりです。

class ClientHelper<T, U> where T : BaseClient<U> {} 

これは無粋になった理由は、私のprojeですctは次のようなクラスに終わります。

class MyClass<A, B, C, D, E, F, G> where A : MyBaseClass<B, C, D, E, F, G> 

1つのタイプを取る基本クラスに至るまでです。これは単にジェネリッククラスの複雑な継承ツリーを持つコストですか、テンプレート化された型の型制限を保持しながらこれを行う簡単な方法ですか?

答えて

5

BaseClientのパブリック・インターフェースが、ジェネリック・タイプ・パラメーターを何らかの形で公開している場合、あなたの「控えめな」ソリューションは正しいものです。

だから、あなたはそれを定義されているようBaseClientないであると仮定すると:そして、TはBaseClientのパブリックインターフェイス契約の一部であり、そのためClientHelperのパブリックインターフェイス契約の一部は(再び、それを想定し

abstract class BaseClient<T> 
{ 
    //Something about T here 
} 

BaseClient<U>はClientHelperのインターフェイスを介して公開されています)。一方

、のは、それは実際にあなたの例がそれを置くようであると仮定してみましょう:その場合は

abstract class BaseClient<T> 
{ 
    //Nothing about T here 
} 

を、あなたが行うことができます:

interface IBaseClient 
{ 
    //Nothing about T here 
} 

abstract class BaseClient<T> : IBaseClient 
{ 
    // Whatever you like here 
} 

ClientHelperは次のようになります。

class ClientHelper<T> where T : IBaseClient 
{ 
} 
+0

私のクラスの中には単に内部的に使う 'T'を公開していないものもあるので、インタフェースはその一部で動作するかもしれません。私はそれが扱いにくくなってきているので、私が得ることができる任意の単純化を取るでしょう。 – Foran

+0

'クラス'を 'T 'が公開されることのないすべてのケースを単純化しました。シンプルだけど、それほど明白ではありませんでした。 :-)それは転送される必要があるタイプのおよそ半分を切り捨てます。 – Foran

+0

Cool。うれしいことはあなたのために働いた。また、タイプに依存しない与えられた 'T'(メソッド、プロパティ、イベント、フィールド)に対して、***オペレーション***をすべて一般化することができれば、いくつかの追加の汎用パラメータを削除することもできます。 –

0

1つのオプションは次のようです:

interface IWebService 
{ 
} 

interface IClient<out T> 
{ 
} 

abstract class BaseClient<T> : IClient<T> 
{ 
} 

class SpecializedClient : BaseClient<IWebService> 
{ 
} 

class ClientHelper<T> where T : IClient<object> 
{ 
} 

BaseClientTを返信し、決して受け付けない場合にのみ動作します。

関連する問題