2009-12-02 28 views
12

Các mã sau đây mang lại cho tôi lỗi này:Tại sao tôi không thể chuyển Danh sách <Customer> làm tham số cho phương thức chấp nhận Danh sách <object>?

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

Làm thế nào tôi có thể chỉ ra để trình biên dịch mà khách hàng thực sự được thừa hưởng từ đối tượng? Hoặc thực hiện nó không làm thừa kế với các đối tượng thu chung chung (gửi List<string> bị lỗi tương tự).

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

Tại sao bạn lại tham gia Danh sách mục? – JonH

+0

để thực hiện phản chiếu trên chúng và xử lý chúng động –

+0

Bạn vẫn có thể thực hiện phản chiếu trên đối tượng 'Customer' giống như bạn có thể trên một' đối tượng'. –

Trả lời

14

.NET không có đồng phương sai và contra-sai (chưa).

B đó xuất phát từ A không ngụ ý rằng List<B> có nguồn gốc từ List<A>. Nó không. Họ là hai loại hoàn toàn khác nhau.

.NET 4.0 sẽ nhận được biến thể giới hạn và phương sai trái ngược.

+1

Tôi không nghĩ hiệp phương sai trong .NET 4 sẽ giúp đỡ trong tình huống này. –

+0

@Mark Byers: tại sao? có vẻ như nó sẽ giúp rất nhiều – Randolpho

+3

@Mark là chính xác. Sự hỗ trợ hiệp phương sai được thêm vào C# được giới hạn cho các giao diện và các đại biểu. Danh sách là loại bê tông và không thể tận dụng lợi thế ở đây – JaredPar

7

C# (hiện tại) không hỗ trợ phương sai cho các loại chung.

Tuy nhiên, nếu bạn đang sử dụng C# 3.0, bạn có thể làm điều này:

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

+1 cho điều này. Nếu bạn là phiên bản trước 3 thì bạn có thể viết một phương thức để chuyển đổi Danh sách thành Danh sách . – Fenton

8

Đó là vấn đề hiệp phương sai và không dễ dàng như khi nhìn vào cảnh đầu tiên. C# 4 sẽ có một số hỗ trợ cho điều đó.

Để có ý tưởng về các sự cố, hãy tưởng tượng trong trường hợp của bạn rằng dàn diễn viên này thực sự sẽ hoạt động. Giờ đây, bạn có một số List<object>, ví dụ: phương thức Add. Tuy nhiên, đối số cho thực tế Add phải là Customer, để điều này rõ ràng vi phạm việc thực hiện; việc triển khai không cung cấp phương thức Add(object obj).

Thật không may, một số vấn đề có thể đã được giải quyết bằng cách sử dụng một thiết kế thông minh (er) của giao diện với các phương pháp chung nơi hiệp phương sai, chẳng hạn như cho GetEnumerator.

6

Đó là vì danh sách lớp không thể chuyển đổi thành danh sách lớp cơ sở. Đó là một quyết định có chủ ý để làm cho ngôn ngữ được an toàn. Câu hỏi này được hỏi thường xuyên.

Here là câu trả lời tiêu chuẩn của tôi về làm thế nào để làm việc xung quanh vấn đề này:

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

hay:

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

Cũng here thực sự là lời giải thích tốt từ Eric Lippert mình, một trong những kiến ​​trúc sư trưởng về nhóm C#.

2

Điều này đã được đề cập đến trong nhiều câu trả lời khác. Câu trả lời ngắn gọn là thế này:

Cân nhắc tôi có các biến:

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

Bây giờ, đây là nơi nó dừng lại soạn:

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

objects.Add("foo"); 

Việc đó có ý nghĩa bây giờ?

C# 4.0 sẽ giới thiệu khả năng hạn chế để làm những gì bạn đang cố gắng, mặc dù có khả năng làm chính xác như bạn mô tả (gán một List<Customer> đến một List<object> sẽ không được phép cho cùng một lý do tôi nêu ở trên). Xem Eric Lippert's blog để biết thêm thông tin và chỉnh sửa một số thông tin sai lệch xảy ra xung quanh mạng nội bộ.

Để giải quyết nhận xét của bạn ở trên, không có lý do gì khiến bạn không thể thực hiện các thao tác phản chiếu tương tự trên ví dụ Customer như bạn có thể trên object.

1

Thay vì đi qua Danh sách mà không làm việc vì những lý do trên, có thể bạn không chỉ đơn giản là vượt qua chỉ là một tham chiếu đối tượng sau đó nhận được các loại danh sách sau đó, kinda như ...

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

Tại sao có thể không phải là tham số được loại IList?

void công khai FillSmartGrid (các mặt hàng IList)

0

Tôi đồng ý với câu trả lời của Winston Smith.

Tôi chỉ muốn chỉ ra thay thế (mặc dù điều này có thể không phải là cách tốt nhất để xử lý tình huống) trong khi List<Customer> không lấy được từ List<Object>, Khách hàng [] xuất phát từ Object [].

Do đó, nó có thể làm điều này:

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

    public void FillSmartGrid(object[] items) 
    { 
    } 

Tất nhiên, nhược điểm là bạn đang tạo ra một đối tượng mảng chỉ để bạn có thể vượt qua nó để chức năng này.

Các vấn đề liên quan