2015-04-12 15 views
6

Đối với mỗi *Collection (HtmlNodeCollection, TreeNodeCollection, CookieCollection vv) Ví dụ lớp mà tôi cần phải vượt qua một phương pháp mà chỉ chấp nhận một mảng hoặc danh sách (nên không có một phương pháp mà chấp nhận một TreeNodeCollection trong TreeView chẳng hạn?) Tôi có để viết một phần mở rộng-phương pháp như thế này:Cách nhanh chóng để chuyển đổi Bộ sưu tập thành Mảng hoặc Danh sách?

public static TreeNode[] ToArray(this TreeNodeCollection nodes) 
     { 
      TreeNode[] arr = new TreeNode[nodes.Count]; 
      nodes.CopyTo(arr, 0); 
      return arr; 
     } 

Hoặc loop trên toàn bộ bộ sưu tập thêm các mục vào một đầu ra danh sách và sau đó chuyển đổi đầu ra-list để một mảng:

public static TreeNode[] ToArray(this TreeNodeCollection nodes) 
     { 
     var output = new List<TreeNode>(); 
      foreach (TreeNode node in nodes) 
       output.Nodes(node); 
      return output.ToArray(); 
} 

Vì vậy, câu hỏi của tôi là: Tôi cần phương pháp mở rộng này thường xuyên. Nó có thể phân bổ rất nhiều bộ nhớ nếu danh sách lớn, như thường lệ. Tại sao tôi không thể lấy tham chiếu (không sao chép) vào mảng nội bộ được sử dụng bởi các lớp học *Collection này để tôi không cần phải sử dụng các tiện ích mở rộng đó và thực hiện phân bổ bộ nhớ này? hoặc thậm chí cung cấp phương thức ToArray(). Chúng ta không cần phải biết việc triển khai thực hiện nội bộ hoặc mảng được sử dụng trong trường hợp cuối cùng của nó.

+5

'Tôi cần chuyển sang phương thức chỉ chấp nhận một mảng hoặc danh sách' Tại sao không 'IEnumerable '? Bạn có thể dễ dàng chuyển 'treeNodeCollection.Cast ()' cho ví dụ. – EZI

+3

Sử dụng 'IEnumerable '. Nếu bạn cần mảng, hãy sử dụng 'collection.Cast () .ToArray()' và loại bỏ hoàn toàn các phương thức mở rộng của bạn. –

+0

'.Cast <>()' thực sự tốt đẹp ... hiện 'collection.Cast () .ToArray()' khác với phần mở rộng '.ToArray()' của tôi (ngoài thực tế nó là bản địa, tất nhiên)? – Jack

Trả lời

10

Lý do khiến tất cả các lớp thu thập BCL ẩn mảng bên trong của chúng là vì các lý do "tính độc đáo của API". Mảng nội bộ có thể thay đổi trong trường hợp cần phát triển hoặc thu nhỏ. Sau đó, bất kỳ mã người dùng nào có tham chiếu đến mảng cũ đều có thể bị nhầm lẫn. Ngoài ra, mã người dùng có thể truy cập vào các chỉ mục mảng không hợp lệ để truy cập vào bộ sưu tập. Nếu bạn có List với Capacity = 16 && Count == 10 và sau đó bạn có thể truy cập mảng nội bộ tại chỉ mục 15 mà danh sách thường không cho phép.

Những vấn đề này khiến API khó sử dụng. Chúng gây ra các vé hỗ trợ và câu hỏi Stack Overflow.

Xóa mã hiện tại của bạn và thay thế bằng:

TreeNodeCollection nodes; 
var myArray = nodes.Cast<TreeNode>().ToArray(); 

Bạn có thể làm điều này vào một phương pháp mở rộng nếu bạn cảm thấy cần cho điều đó. Nhập tham số là IEnumerable (không có generics). Đó là một bí ẩn đối với tôi tại sao các bộ sưu tập hiện tại trong BCL chưa được nâng cấp để thực hiện IEnumerable<T>. Đó là lý do tại sao bạn cần số Case. I just created a User Voice item for this.

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