2013-03-24 24 views
7

Tôi đang cố gắng tạo phương thức trả về danh sách bất kỳ loại người dùng nào muốn. Để làm điều này tôi đang sử dụng Generics, mà tôi không quá quen thuộc với vì vậy câu hỏi này có thể được rõ ràng. Vấn đề là mã này không hoạt động và ném các thông báo lỗi Cannot convert type Systems.Collections.Generic.List<CatalogueLibrary.Categories.Brand> to Systems.Collection.Generic.List<T>Có thể sử dụng IList nhưng không Danh sách theo phương pháp chung

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

    } 
    ... 
} 

Nhưng nếu tôi sử dụng IList thay vào đó, không có lỗi.

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

    } 
    ... 
} 

Tại sao tôi có thể sử dụng IList nhưng không liệt kê trong trường hợp này? collection.Brands trả về loại BrandCollection từ thư viện của bên thứ ba vì vậy tôi không biết cách tạo. Nó có thể được rằng BrandCollection có thể xuất phát từ IList (chỉ đoán rằng nó không) và do đó, nó có thể được chuyển đổi sang nó, nhưng không đến một danh sách bình thường?

+0

Bạn nên đặt các ràng buộc loại trên đó! Bạn không thể chỉ đi xung quanh việc đúc những thứ vớ vẩn. – antonijn

+3

Bạn có chắc chắn ví dụ thứ hai của bạn không phải là bộ sưu tập 'return (IList ).Brands.ToList ();'? – Matthew

+0

Tôi sẽ xem xét sau khi làm việc này. Tôi là một chút mới để generics vì vậy figured tôi muốn để lại cho đến khi sau này trong trường hợp nó đã phá vỡ một cái gì đó khác: D Liệu ràng buộc là 'nơi T: Brand' (và các loại khác)? – XSL

Trả lời

9

Vì không có ràng buộc nào trên T, bạn chỉ có thể chuyển đổi thành object lúc biên dịch. Các giao diện cho các kiểu giao diện không được trình biên dịch kiểm tra vì có thể về mặt lý thuyết là một lớp mới được tạo mà triển khai thực hiện IList<object> và kế thừa List<Brand>. Tuy nhiên, các diễn viên để List<T> sẽ thất bại vì nó được biết rằng không thể có một lớp được tạo ra mà kế thừa cả hai List<object>List<Brand>. Tuy nhiên, trong trường hợp của bạn, bạn biết loại T là thông qua tuyên bố switch của bạn và muốn ép buộc diễn viên. Để làm điều này, đúc thông qua object đầu tiên như sau:

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

Thiết kế vấn đề lớn ở đây, tuy nhiên, là Generics không phải là lựa chọn tốt nhất khi bạn có một danh sách rời rạc của các loại biết đến với T. Generics là tốt hơn khi T có thể là bất cứ điều gì, hoặc bị ràng buộc với một loại cơ sở hoặc giao diện. Ở đây, bạn sẽ được tốt hơn off chỉ cần viết một phương pháp riêng cho từng chi nhánh của câu lệnh switch:

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

Nếu không có điều này, bạn có rất ít an toàn loại. Nếu ai đó gọi phương thức của bạn với ConvertToList<int>(Category.Brands) thì sao?

+0

Cảm ơn lời giải thích. Mặc dù phương thức 'object' đã làm việc, tôi sẽ đi cho tuyến đường phương thức riêng lẻ. Tôi sẽ không thể hạn chế được 'Thương hiệu' như tôi vừa phát hiện ra rằng đó là một lớp học bị phong ấn. – XSL

+0

+1. Tôi nghĩ lý do thực sự là do tham chiếu C# 6.2.4: "Chuyển đổi tham chiếu rõ ràng là ...\t Từ * bất kỳ loại S * nào đến * bất kỳ kiểu giao diện T * nào, với điều kiện S không được niêm phong và cung cấp S không thực hiện T. " –

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