2009-12-02 6 views
12

次のコードは、私は、このエラーを与える:List <object>を受け入れるメソッドに、リスト<Customer>をパラメータとして渡すことができないのはなぜですか?

Cannot convert from 'System.Collections.Generic.List' to 'System.Collections.Generic.List'.

にはどうすればお客様が実際にオブジェクトを継承するコンパイラに指示することができますか?または、汎用コレクションオブジェクトで継承を行っていないだけです(List<string>を送信すると同じエラーが発生します)。

using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Documents; 

namespace TestControl3423 
{ 
    public partial class Window2 : Window 
    { 
     public Window2() 
     { 
      InitializeComponent(); 

      List<Customer> customers = Customer.GetCustomers(); 
      FillSmartGrid(customers); 

      //List<CorporateCustomer> corporateCustomers = CorporateCustomer.GetCorporateCustomers(); 
      //FillSmartGrid(corporateCustomers); 
     } 


     public void FillSmartGrid(List<object> items) 
     { 
      //do reflection on items and display dynamically 
     } 
    } 

    public class Customer 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
     public string Street { get; set; } 
     public string Location { get; set; } 
     public string ZipCode { get; set; } 

     public static List<Customer> GetCustomers() 
     { 
      List<Customer> customers = new List<Customer>(); 
      customers.Add(new Customer { FirstName = "Jim", LastName = "Jones", ZipCode = "23434" }); 
      customers.Add(new Customer { FirstName = "Joe", LastName = "Adams", ZipCode = "12312" }); 
      customers.Add(new Customer { FirstName = "Jake", LastName = "Johnson", ZipCode = "23111" }); 
      customers.Add(new Customer { FirstName = "Angie", LastName = "Reckar", ZipCode = "54343" }); 
      customers.Add(new Customer { FirstName = "Jean", LastName = "Anderson", ZipCode = "16623" }); 
      return customers; 
     } 
    } 
} 
+2

なぜあなたはリストのアイテムを取り入れていますか? – JonH

+0

がリフレクションを行い、それらを動的に処理する –

+0

'Customer'オブジェクトの場合と同じようにリフレクションを実行することができます。 –

答えて

14

.NET共分散と(まだ)コントラ分散を持っていません。

Aが由来するものは、List<B>List<A>に由来することを意味しません。それはしません。彼らは全く異なる2つのタイプです。

.NET 4.0では、限定された共分散と逆分散が得られます。

+1

.NET 4の共分散がこのような状況で役に立つとは思わない。 –

+0

@Mark Byers:なぜですか?それは多くを助けるように見える – Randolpho

+3

@マークが正しいです。 C#に追加される共分散サポートは、インターフェイスと代理人に限られています。リストは具体的なタイプであり、ここでは利用できません – JaredPar

7

C#(現時点では)はジェネリック型の分散をサポートしていません。しかし

、あなたがC#3.0を使用している場合、あなたはこれを行うことができます。

FillSmartGrid(customers.Cast<object>()); 
+1

+1。バージョン3より前のバージョンの場合は、リストをリストに変換する方法を記述できます。 – Fenton

8

これは共分散の問題であり、一見するとそれほど簡単ではありません。 C#4はそれをいくらかサポートします。

問題のアイデアを得るには、このキャストが実際に機能することをあなたのケースで想像してください。今あなたはList<object>を持っています。例えば、Addメソッドもあります。しかし、実際のAddの引数はCustomerでなければなりません。これは明らかに実装に違反します。実装ではAdd(object obj)メソッドが提供されません。

残念ながら、GetEnumeratorのように、共分散がOKの汎用メソッドでインターフェイスのスマートなデザインを使用すると、いくつかの問題が解決されている可能性があります。

6

これは、クラスのリストが基本クラスのリストに変換できないためです。言語を安全にするという意図的な決定です。この質問は頻繁に尋ねられます。

Hereは、問題を回避する方法の私の標準の答えです:

List<A> listOfA = new List<C>().ConvertAll(x => (A)x); 

か:また

List<A> listOfA = new List<C>().Cast<A>().ToList(); 

hereはエリックリペット自身、上の主任建築家の一人から本当に良い説明ですC#チーム

2

これは、他の多くの回答の中に含まれています。短い答えはこれです:

は、私はこれらの変数を持って考えてみましょう:それはコンパイルを中止しどこ

List<Customer> customers = new List<Customer>(); //ok, seems fair 
List<object> objects = new List<object>(); // again, everything's fine 

は今、ここにある:

objects = customers; // sounds OK, since a Customer is an object, right? 

objects.Add("foo"); 

ん、今理にかなっていますか?

C#4.0は正確にあなたが(List<object>List<Customer>を割り当てるには、私が上記で概説した同じ理由のために許可されません)説明するようを行うことができることが、あなたがしようとしている何をすべきか限られた能力を紹介します。詳細については、Eric Lippert's blogを参照してください。

上記のご意見を解決するには、objectの場合と同じようにCustomerインスタンスで同じ反射操作を実行できない理由はありません。代わりに、上記の理由のために動作しませんリストを渡すの

1

、あなたは、単に、その後のようなちょっと、その後リストの種類を入手するには、オブジェクト参照を渡すことができませんでした...

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 { 

    class Customer { 
     public int id; 
     public string name; 
    } 

    class Monkey { 

     public void AcceptsObject(object list) { 

      if (list is List<Customer>) { 
       List<Customer> customerlist = list as List<Customer>; 
       foreach (Customer c in customerlist) { 
        Console.WriteLine(c.name); 
       } 
      } 
     } 
    } 

    class Program { 
     static void Main(string[] args) { 

      Monkey monkey = new Monkey(); 
      List<Customer> customers = new List<Customer> { new Customer() { id = 1, name = "Fred" } }; 
      monkey.AcceptsObject(customers); 
      Console.ReadLine(); 
     } 
    } 
} 
0

できないのはなぜパラメータはIList型ですか?

ます。public void FillSmartGrid(IListの項目)

0

私はウィンストン・スミスの答えに同意します。

は、私はちょうど List<Customer>ながら List<Object>から派生していないこと(これはおそらく状況に対処するための最良の方法ではありませんが)の代替として指摘したかった、お客様は[] [] Objectから派生ありません。

したがって、これを行うことが可能である。もちろん

{ 
     List<Customer> customers = new List<Customer>(); 
     // ... 
     FillSmartGrid(customers.ToArray()); 
     // ... 
    } 

    public void FillSmartGrid(object[] items) 
    { 
    } 

を、欠点は、あなたがこの関数に渡すことができちょうどので、配列オブジェクトを作成しているということです。

関連する問題