2012-04-11 13 views
3

このテクニックを使用している他の開発者に気づいたことがありますが、それは常に私を混乱させました。私は今朝調査することを決めたと(http://msdn.microsoft.com/en-us/library/d5x73970(v=vs.100).aspxから)MSDNで次出くわし:タイプパラメータ制約はクラス

public class GenericList<T> where T : Employee 
{ 
... 
} 

は、なぜ私たちはクラスで従業員とTのすべてのインスタンスを置き換えるのではなく、このメソッドを使用するのでしょうか?私には、これは保守性の勝利のようです。異なる継承階層のクラスを含める手段としてインターフェースに制限することは理解できますが、継承はすでに上の問題をより明白な方法で既に解決していますか?

これは間違いと見なされることがありますか、このようなコードを '修正'するのは間違いでしょうか?

+0

を持っている場合、私はまだこの方法を見てきたと思います

GenericList<Manager> managers = .... managers[0].CalculateManagerBonus(); 

を行うことができます非汎用的なアプローチがより適切である場合に使用され、私のビジョンがより受け入れられる用途にぼやけている可能性があります。 – Sprague

+0

@sprague:例を挙げることはできますか?好ましくはlibから? –

+0

@Henk Holterman:タイプパラメータが不必要な場合があると言うことで十分です。これはそのようなケースでしたが、私は主に、制約内に特定のクラスを持つ型パラメータの妥当なケースに興味がありました。私はそのような使用(あなたと他のおかげで、私は今やっている)の事例を理解するまで状況を判断してはいけませんでした。 – Sprague

答えて

7

Employeeから派生したものかもしれません。

public class EvilEmployee : Employee { 
    public Int32 Evilness { get; set; } 
} 

それを行うようになりました...

GenericList<EvilEmployee> list = GetEvilEmployees(); 
var mostEvilEmployee = list.OrderByDescending(e => e.Evilness).First(); 

私たちが知っているので、それはT = EvilEmployeeとそのEvilEmployeeが邪悪特性を持っていることを、コンパイル時に、可能です。 (OfTypeを使用せずに)可能ではないEmployeeのリストにリストを強制する場合。

+0

増幅する場合:クラスに制約のあるジェネリック型Tのクラスに、T型またはTを含む型のいずれかを返すメソッドがない場合、T型のref/outパラメータもTを含む型もなく、型のコンシューマは受け入れられませんTまたはTを含むタイプの場合、一般に、タイプTのすべての出現を制約タイプに置き換えることができる。クラス自体はジェネリックの拘束型に代わるものではありませんが、前述のリターン型またはパラメータ型のいずれかがある場合、派生型のクラスを使用するコードには問題があります。 – supercat

5

Tのすべてのインスタンスをクラス内のEmployeeに置き換えるのではなく、なぜこのメソッドを使用したいのですか?

を有効にするには:あなたの名前「GenericList」は、このシナリオではより多くのようになる

class Manager : Employee { ... } 

var board = new GenericList<Manager>(); 

注意「をEmployeeListも」私はの手段としてのインターフェースに制限を理解することができます

異なる継承階層からのクラスを含むクラス

クラス継承およびインターフェイスsは共通点が多い。

しかし、継承は既に上記の問題をより明白な方法で解決していますか?

はい、同じではありません。 board.Add(lowlyProgrammer);は、継承が許可している間はここで失敗します。

+0

マネージャは既に従業員ですが、これは既に多態性で可能です...私は何かを欠いている? – Sprague

+0

@Sprague: 'board.Add(lowlyProgrammer);'ここで失敗するでしょう。 –

+1

+1簡潔 - ジェネリックにタイプ階層セーフティを適用する簡単な方法ですが、イン/アウトタイプ(例えばadd/getメソッド)はタイプ 'T'と同じです。呼び出し元が非ジェネリックであった場合の呼び出し元の使用を簡素化します。 –

0

ここで、ステートメントは意図的に追加されています。 Employeeクラスから派生したクラスがある状況を考えてみましょう。ジェネリッククラスを定義しない場合は、派生クラスごとにクラスを定義する必要があります。

たとえば、EmployeeXがEmployeeを継承し、ListのみをEmployeeXインスタンスを受け入れるように定義する場合は、汎用アプローチを使用して新しいクラスを定義する必要はありません。

0

ジェネリックスを使用すると、キャストする必要なくタイルセーフにすることができます。

あなたは

public class Manager : Employee 
    { 
    public double CalculateManagerBonus(); 
    } 

を持っている場合は、これが今の私には理にかなっている間、あなたが

GenericList<Employee> managers = .... 

    // this is a compiler error 
    managers[0].CalculateManagerBonus(); 

    // this is neccessary if there where no generics. 
    ((Manager)managers[0]).CalculateManagerBonus(); 
関連する問題