2011-10-03 43 views
15

Tôi có một chức năng như thế này:Làm cách nào để chuyển Danh sách lớp học sang Danh sách Giao diện?

DoSomething(List<IMyInterface>) 

IMyInterface là một giao diện và MyClass là một lớp thực hiện giao diện này lớp MyClass: IMyInterface

tôi gọi DoSomething(List<MyClass>) và có vẻ nó không hoạt động. Làm thế nào tôi có thể chuyển danh sách của một lớp vào danh sách giao diện của lớp như tham số của hàm? Cảm ơn!

+0

mã của bạn là gì? – talnicolas

Trả lời

26

Nếu mã của bạn chỉ đơn giản là lặp qua chuỗi bên trong phương pháp này (không thêm, xóa, hoặc truy cập bởi chỉ số), thay đổi phương thức của bạn với một trong những

DoSomething(IEnumerable<IMyInterface> sequence) 
DoSomething<T>(IEnumerable<T> sequence) where T : IMyInterface 

Giao diện IEnumerable<> Sau đây là hiệp biến (như của .NET 4) (tùy chọn đầu tiên). Hoặc bạn có thể sử dụng chữ ký sau nếu sử dụng C# 3.

Nếu không, nếu bạn cần các hoạt động được lập chỉ mục, hãy chuyển đổi danh sách trước khi chuyển nó. Trong lời gọi, bạn có thể có

// invocation using existing method signature 
DoSomething(yourList.Cast<IMyInterface>().ToList()); 

// or updating method signature to make it generic 
DoSomething<T>(IList<T> list) where T : IMyInterface 

gì chữ ký sau này sẽ cho phép bạn làm là cũng để hỗ trợ thêm hoặc loại bỏ vào danh sách (có thể nhìn thấy tại callsite), và nó cũng sẽ cho phép bạn sử dụng danh sách mà không đầu tiên sao chép nó.

Ngay cả khi vẫn còn, nếu tất cả những gì bạn làm là lặp qua danh sách trong một vòng lặp, tôi sẽ ưu tiên một phương pháp acceping IEnumerable<>.

+0

Đối với các thao tác và loại bỏ được lập chỉ mục, sẽ không phải là 'DoSomething (danh sách IList ) trong đó T: IMyInterface' cũng hoạt động? (Nếu không cần danh sách được sao chép.) – millimoose

+0

@Sli, vâng, anh ta có thể làm cho phương pháp chung chung. Tôi đã cập nhật để hiển thị các tùy chọn chung. –

+0

Một giải pháp thay thế sẽ là định nghĩa một giao diện IReadableList , và sau đó viết một lớp bao bọc thực hiện cả hai điều đó và IList . Tuy nhiên, mã khác sẽ phải được thay đổi để sử dụng lớp trình bao bọc. Người ta có thể xác định một chuyển đổi mở rộng từ một List thành ListWrapper , nhưng điều đó sẽ hơi khốc liệt và nó sẽ không giúp hệ thống nhận ra rằng một Danh sách có thể được biến thành một cái gì đó (ListWrapper ) thực hiện IReadableList . – supercat

7

Điều này không an toàn nói chung vì Danh sách có thể thay đổi. Giả sử bạn vượt qua ai đó một tham chiếu đến một List<MyClass> như một List<IMyInterface>, sau đó họ làm:

void Foo(List<IMyInterface> list) 
{ 
    IMyInterface x = new MyOtherClassWhichAlsoImplementsIMyInterface(); 
    list.Add(x); 
} 

Bây giờ bạn List<MyClass> chứa một thể hiện của một lớp học mà không phải là một MyClass. Điều này sẽ vi phạm loại an toàn. (Như các câu trả lời khác được lưu ý, bạn có thể tránh vấn đề này bằng cách chỉ chuyển giao diện IEnumerable<> của Danh sách, cung cấp quyền truy cập chỉ đọc và an toàn).

Để biết thêm chi tiết, hãy xem Using Variance in Interfaces for Generic Collections on MSDN. Xem thêm a good summary of covariance and contravariance and various C# features that support it.

0

Nếu bạn chỉ cần duyệt qua danh sách, hãy khai báo phương thức bằng IEnumerable. Nếu bạn muốn thêm các phần tử vào danh sách, những gì bạn đang yêu cầu không an toàn và có thể không được phép trong C#.

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