không có AddRange()
phương pháp cho IList<T>
.
Làm cách nào để thêm danh sách các mục vào a IList<T>
mà không cần lặp lại các mục và sử dụng Add()
phương thức?
không có AddRange()
phương pháp cho IList<T>
.
Làm cách nào để thêm danh sách các mục vào a IList<T>
mà không cần lặp lại các mục và sử dụng Add()
phương thức?
Câu trả lời:
AddRange
được xác định trên List<T>
, không phải giao diện.
Bạn có thể khai báo biến List<T>
thay vì IList<T>
hoặc ép kiểu nó để có List<T>
quyền truy cập AddRange
.
((List<myType>)myIList).AddRange(anotherList);
Đây không phải là thực hành tốt (xem bình luận dưới đây), như là một IList<T>
sức mạnh không thể là một List<T>
, nhưng một số loại khác mà thực hiện giao diện và có thể rất sẽ không có một AddRange
phương pháp - trong trường hợp này, bạn sẽ chỉ tìm hiểu khi mã của bạn ném một ngoại lệ trong thời gian chạy.
Vì vậy, trừ khi bạn biết chắc chắn rằng loại thực sự là loại List<T>
bạn không nên cố gắng sử dụng AddRange
.
Một cách để làm như vậy là kiểm tra kiểu với toán tử is hoặc as (kể từ C # 7).
if(myIList is List<T>)
{
// can cast and AddRange
}
else
{
// iterate with Add
}
List<T>
(hoặc, nếu đây không phải là lựa chọn tốt cho bạn, hãy truyền diễn viên ở nơi bạn cần để AddRange
bản địa hóa - đó là một hoạt động chi phí rất thấp ).
InvalidCastException
được sử dụng trên bất kỳ thứ gì khác ngoài List<T>
(ví dụ: mảng).
Nếu bạn nhìn vào mã nguồn c # cho List , tôi nghĩ rằng List.AddRange () có những tối ưu hóa mà một vòng lặp đơn giản không giải quyết được. Vì vậy, một phương thức mở rộng chỉ cần kiểm tra xem IList có phải là một Danh sách hay không và nếu có thì hãy sử dụng AddRange () gốc của nó.
Nhìn xung quanh mã nguồn, bạn thấy những người .NET làm những việc tương tự trong phần mở rộng Linq của riêng họ cho những thứ như .ToList () (nếu đó là một danh sách, hãy truyền nó ... nếu không hãy tạo nó).
public static class IListExtension
{
public static void AddRange<T>(this IList<T> list, IEnumerable<T> items)
{
if (list == null) throw new ArgumentNullException(nameof(list));
if (items == null) throw new ArgumentNullException(nameof(items));
if (list is List<T> asList)
{
asList.AddRange(items);
}
else
{
foreach (var item in items)
{
list.Add(item);
}
}
}
}
list
đến List<T>
hai lần ở đây. Một trong số đó có thể được tối ưu hóa với as
từ khóa.
if (list is List<T> castedList) { castedList.AddRange(items); }
Bạn có thể làm điều gì đó như sau:
IList<string> oIList1 = new List<string>{"1","2","3"};
IList<string> oIList2 = new List<string>{"4","5","6"};
IList<string> oIList3 = oIList1.Concat(oIList2).ToList();
Vì vậy, về cơ bản bạn sẽ sử dụng Concat()
tiện ích mở rộng và ToList()
để có được một chức năng tương tự như AddRange()
.
Enumerable.Concat
được triển khai bởi System.Linq.Enumerable
và giá trị trả về của phương thức đó IEnumerable<TSource>
, vì vậy tôi tin rằng nó không nên được chuyển trở lại IList<TSource>
- nó có thể trả về thứ gì đó khác do chi tiết triển khai mà chúng tôi không biết nếu không kiểm tra mã nguồn - mặc dù vậy, không có gì đảm bảo rằng nó sẽ không thay đổi - vì vậy cần đặc biệt chú ý khi hỗ trợ nhiều phiên bản .NET.
Bạn cũng có thể viết một phương thức mở rộng như sau:
internal static class EnumerableHelpers
{
public static void AddRange<T>(this IList<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
{
collection.Add(item);
}
}
}
Sử dụng:
IList<int> collection = new int[10]; //Or any other IList
var items = new[] {1, 4, 5, 6, 7};
collection.AddRange(items);
Cái này vẫn đang lặp lại các mục, nhưng bạn không phải viết lần lặp hoặc ép kiểu mỗi khi bạn gọi nó.
Concat
Truyền hoặc sử dụng LINQ , như @Self_Taught_Programmer đã trả lời .