public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
Làm thế nào tôi có thể truyền List<Client>
đến List<IDic>
?
public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
Làm thế nào tôi có thể truyền List<Client>
đến List<IDic>
?
Câu trả lời:
Bạn không thể truyền nó (duy trì danh tính tham chiếu) - điều đó sẽ không an toàn. Ví dụ:
public interface IFruit {}
public class Apple : IFruit {}
public class Banana : IFruit {}
...
List<Apple> apples = new List<Apple>();
List<IFruit> fruit = apples; // Fortunately not allowed
fruit.Add(new Banana());
// Eek - it's a banana!
Apple apple = apples[0];
Bây giờ bạn có thể chuyển đổi a List<Apple>
thành an IEnumerable<IFruit>
trong .NET 4 / C # 4 do hiệp phương sai, nhưng nếu muốn có, List<IFruit>
bạn phải tạo một danh sách mới . Ví dụ:
// In .NET 4, using the covariance of IEnumerable<T>
List<IFruit> fruit = apples.ToList<IFruit>();
// In .NET 3.5
List<IFruit> fruit = apples.Cast<IFruit>().ToList();
Nhưng điều này không giống như đúc danh sách ban đầu - bởi vì bây giờ có hai danh sách riêng biệt . Điều này là an toàn, nhưng bạn cần hiểu rằng các thay đổi được thực hiện cho một danh sách sẽ không được nhìn thấy trong danh sách kia. ( Tất nhiên sẽ thấy các sửa đổi đối với các đối tượng mà danh sách đề cập đến.)
List<IFruit>
thực sự là tham chiếu đến a List<Apple>
. Điều gì bạn mong đợi sẽ xảy ra nếu bạn thêm một Banana
tham chiếu vào đó List<IFruit>
?
using
chỉ thị cho System.Linq
, hoặc những gì bạn đang cố gắng gọi nó về, tôi không chắc chắn làm thế nào bạn mong đợi tôi để có thể giúp đỡ. Tôi khuyên bạn nên nghiên cứu thêm, và nếu bạn vẫn gặp khó khăn, bạn hãy đặt một câu hỏi với một ví dụ có thể tái tạo tối thiểu .
Một trình lặp Cast và .ToList ():
List<IDic> casted = input.Cast<IDic>().ToList()
sẽ thực hiện thủ thuật.
Ban đầu tôi đã nói hiệp phương sai sẽ hoạt động - nhưng như Jon đã chỉ ra một cách đúng đắn; không nó sẽ không!
Và ban đầu tôi cũng đã bỏ ToList()
cuộc gọi một cách ngu ngốc
Cast
trả về một IEnumerable<T>
, không phải a List<T>
- và không, hiệp phương sai sẽ không cho phép chuyển đổi này, vì nó sẽ không an toàn - hãy xem câu trả lời của tôi.
ToList()
thiếu sót trước khi đọc bình luận của bạn; nhưng có như bạn đã trình bày tất nhiên Covariance sẽ không hoạt động! Doh!
Cast
gọi trong .NET 4, miễn là bạn chỉ định đối số kiểu ToList
.
Tôi cũng gặp vấn đề này và sau khi đọc câu trả lời của Jon Skeet, tôi đã sửa đổi mã của mình từ sử dụng List<T>
sang sử dụng IEnumerable<T>
. Mặc dù điều này không trả lời câu hỏi ban đầu của OP về Làm thế nào tôi có thể truyền List<Client>
tớiList<IDic>
, nhưng nó tránh được sự cần thiết phải làm như vậy và do đó có thể hữu ích cho những người khác gặp phải vấn đề này. Tất nhiên, điều này giả định rằng mã yêu cầu sử dụng List<IDic>
nằm trong tầm kiểm soát của bạn.
Ví dụ:
public void ProcessIDic(IEnumerable<IDic> sequence)
{
// Implementation
}
Thay vì:
public void ProcessIDic(List<IDic> list)
{
// Implementation
}
List<Client> listOfA = new List<Client>();
List<IDic> list = listOfA.Cast<IDic>().ToList();
Chỉ có thể bằng cách tạo mới List<IDic>
và chuyển giao tất cả các yếu tố.
Trong .Net 3.5, bạn có thể làm như sau:
List<ISomeInterface> interfaceList = new List<ISomeInterface>(list.Cast<ISomeInterface>());
Hàm tạo cho Danh sách trong trường hợp này lấy IEnumerable. mặc dù
danh sách chỉ có thể chuyển đổi thành IEnumerable. Mặc dù myObj có thể chuyển đổi thành ISomeInterface nhưng loại IEnumerable không thể chuyển đổi thành IEnumerable.