2012-03-29 14 views
0

C#クラス、インタフェースおよび制約

は、私が「ITemplate」と呼ばれるインターフェースを持っていると私はそのインターフェイスに基づいたクラス「テンプレート」の数を定義するとします。

  • TemplateA
  • TemplateB
  • ....
  • TemplateZ

私は

List<ITemplate> myList = new List<ITemplate>(); 
myList.Add(TemplateA); 
myList.Add(TemplateC); 
myList.Add(TemplateX); 

などを使用することができます任意のテンプレートのリストを作成したい場合 - それはです良い。

言って、今私は

myListAlphaTemplatesだけで、すべてのテンプレートの定義されたサブセットを持つことができ、かつ myListBetaTemplatesだけで、すべてのテンプレートの異なる定義されたサブセットを持つことができるように、特別なリストの数を作成したい

何これを達成する最善の方法は何ですか?

だから、現時点で私が持っているコードは次の行に沿っている(実際のコードを投稿するには大きすぎる)

テンプレートインターフェイスを定義し

interface ITemplateConstraint 
{ } 

リストごとに複数のインターフェースを定義します

interface SpecialListOne : ITemplateConstraint 
{ } 

interface SpecialListTwo : ITemplateConstraint 
{ } 

を入力し今、私は実際の "テンプレート"

を定義します

は、そして最後に、私は私のリストに追加

List<SpecialListOne> ListofTypeOne; // this can be TemplateA or TemplateB 
List<SpecialListTwo> ListofTypeTwo; // this can be TemplateA or TemplateC 

これはうまく動作しますが、...

テンプレートのすべてが別のライブラリであり、私は新しいリストを作成する必要がある場合は

「SpecialListThree "これにはTemplateCしかありませんが、実際のテンプレート定義自体を修正する必要はありません。

+0

コンパイルするコードを投稿してください - C#は大文字と小文字を区別します、 'LIST <>!= List <>'です。 – Oded

+3

'すべてのテンプレートの定義されたサブセットのみを持つことができます'どのサブセットの条件を知っていますかここであなたを助ける方法がわかりません。 – asawyer

答えて

1

あなたは制約が任意の条件である場合、あなたはおそらく独自のクラスのラッピングインナーリストの実装を記述する必要があり、このような

public class MyList<T> : List<T> where T:ITemplate, new() { } 

var specialList1 = new MyList<TemplateA>(); 
var specialList2 = new MyList<TemplateB>(); 

ように、コードを使用することができますTypeでリストを制限するためにあなたのしたい場合。しかし、制約はコンパイル時ではなく実行時に発生します。例:

public class ConstrainedList<T> : IList<T> where T:ITemplate 
{ 
    private List<T> _inner = new List<T>(); 
    Func<T, bool> _constraint; 

    public ConstrainedList<T>(Func<T, bool> predicate) 
    { 
     _constraint = predicate; 
    } 

    #Region IList Implementation 

    public void Add(T item) 
    { 
     if (_constraint(item)) 
     { 
      _inner.Add(item); 
     } 
     else 
     { 
      throw new ArgumentException("Does not meet necessary constraint"); 
     } 
    } 

    // rest of implementation 
    ... 

    #End Region 
} 

var specialList1 = new ConstrainedList<ITemplate>(t => null != t && typeof(TemplateA) == t.GetType()); 
var specialList2 = new ConstrainedList<ITemplate>(t => null != t && t.SomeMethod() >= 3); 
-1
interface IQalifiedTemplate 
{ 
    bool IsQaulified(args); 
    ITemaplate Template {get;} 
} 

または

interface IQalifiedTemplate 
    : ITemplate 
{ 
    bool IsQaulified(args); 
} 

あなたはそれがリストに追加するかどうかを決定するためにIsQualified(...)を使用することができます。

+0

彼は追加するかどうかを知る必要はありません。hwは特別なものしか含んでいないlsiを望んでいます。さもなければ、彼はオブジェクトがクラスであるかどうかをチェックすることができる。 – SimpleVar

+0

これを使用して、リストに追加できるかどうかを判断できます。追加できるものを強制する。 –

+0

リストには他の種類のITテンプレートも含めることができます。あなたが示唆していることは強制的ではない - それはフィルタリングです。そして、簡単なフィルタリングのために、彼はboolプロパティを必要としません。 – SimpleVar

0

ロジックがある場合は、特殊クラスをインターフェイスを実装する抽象的な特殊クラスから継承させるか、通常のクラスから継承する特別なインターフェイスを実装させるようにします。

それ以外の場合は、それを知らせません。

4

かなり簡単ですが、Enumerable<>には、拡張方法OfType<>があります。

その使用の例は次のようになります。

var myList = new List<ITemplate>(); 
myList.Add(TemplateA); 
myList.Add(TemplateC); 
myList.Add(TemplateX); 

var myListAlphaTemplates = myList.OfType<AlphaTemplateClass>().ToList(); 
+0

私はこれが大好きです。それらをすべて読み込んでリストをフィルタリングしてください:)私のアプローチよりもはるかに簡単です –

+2

+1しかし技術的には 'List <>'にはメソッドがありません - IEnumerable <>に適用できる拡張機能です –

+0

補正。ありがとうAndras! – Khan

1

あなたはITemplateに基づいて、あなたのアルファおよびベータテンプレートのためのインタフェースを作成し、あなたの特定のクラスがそれらを実装することができます:

IAlphaTemplate : ITemplate {} 

IBetaTemplate : ITemplate {} 

TemplateA : IAlphaTemplate {} 

TemplateB : IBetaTemplate {} 

// etc. 

var myListAlphaTemplates = new List<IAlphaTemplate>(); 
var myListBetaTemplates = new List<IBetaTemplate>(); 
+0

はい、これは現在の方法とまったく同じです。私が持っている問題は、「GammaTemplates」という新しい特別なリストが必要な場合、既存のテンプレートのコードをすべて開かなくても達成できる方法があるということです。これは私の場合は別のアセンブリいくつかのアプリケーション。 –

0

あなたはインタフェースを実装する抽象クラスを定義し、それから継承して具体的な実装を定義することができます。まあ

関連する問題