2013-03-24 49 views
7

ユーザーが希望するタイプのリストを返すメソッドを作成しようとしています。これを行うにはジェネリックスを使用していますが、これはあまりよく知られていないので、この質問は明白かもしれません。問題は、このコードは動作しないということで、エラーメッセージCannot convert type Systems.Collections.Generic.List<CatalogueLibrary.Categories.Brand> to Systems.Collection.Generic.List<T>リストを使用することはできますがIListを使用することはできません。

private List<T> ConvertToList<T>(Category cat) 
{    
    switch (cat) 
    { 
     case Category.Brands: 
      return (List<T>)collection.Brands.ToList<Brand>(); 

    } 
    ... 
} 

をスローしかし、私は代わりにIListを使用している場合、エラーはありません。

private IList<T> ConvertToList<T>(Category cat) 
{    
    switch (cat) 
    { 
     case Category.Brands: 
      return (IList<T>)collection.Brands.ToList<Brand>(); 

    } 
    ... 
} 

なぜこのリストではなくIListを使用できますか? collection.Brandsは、第三者図書館からBrandCollection型を返します。したがって、その作成方法はわかりません。 BrandCollectionはIListから派生しているかもしれません(ちょうどそのことを推測している)ので、それを通常のListに変換することはできますか?

+0

あなたは型制約をそこに置くべきです!あなたは、まるで卑劣なものをキャスティングするだけでは行けません。 – antonijn

+3

2番目の例が 'return(IList )collection.Brands.ToList ();'ではありませんか? – Matthew

+0

これが働いた後、私は見ていきました。私はジェネリックに少し新しかったので、それが後で何か他のものを壊したときにそれを残すと思った:D制約は 'どこT:ブランド'(および他のカテゴリ)であろうか? – XSL

答えて

9

Tには制約がないため、コンパイル時にはobjectにしか変換できません。 IList<object>を実装し、List<Brand>を継承する新しいクラスが理論的に作成できるため、インターフェイスタイプへのキャストはコンパイラによってチェックされません。しかし、List<object>List<Brand>の両方を継承するクラスを作成することはできないことが知られているため、List<T>へのキャストは失敗します。しかし、あなたのケースでは、タイプTがあなたのswitchステートメントによってどのようなものであるかを知っていて、強制的にキャストしたいと思います。

private List<T> ConvertToList<T>(Category cat) 
{    
    switch (cat) 
    { 
     case Category.Brands: 
      return (List<T>)(object)collection.Brands.ToList<Brand>(); 
    } 
} 

ここで大きな設計上の問題は、しかし、あなたはTのための既知の種類の個別のリストを持っている場合、ジェネリック医薬品が最良の選択ではないということです。次のようにこれを行うには、object第1貫通キャスト。 Tが何でもか、基本タイプまたはインタフェースに制約されている場合は、ジェネリックスが優れています。ここで、あなただけのswitch文の各ブランチのために別々の方法を書いたほうが良いと思います。これがないと

private List<Brand> ConvertToBrandList() 
{ 
    return collection.Brands.ToList<Brand>(); 
} 

、あなたは非常に少ないタイプの安全性を持っています。誰かがあなたのメソッドをConvertToList<int>(Category.Brands)で呼び出すとどうなりますか?

+0

を使用することができます。 'object'メソッドは機能しましたが、私は個々のメソッドルートを探します。私はちょうどそれが封印されたクラスであることを知ったので、私は「ブランド」に拘束することができません。 – XSL

+0

+1。本当の理由はC#リファレンス6.2.4によると思います。「明示的な参照変換は...\t * Sが封印されておらず、SがTを実装していない場合は、*任意のクラス型S *から*任意のインタフェース型T * –

関連する問題