A quick way to convert a collection to an array or list?

For each instance of the *Collection class ( HtmlNodeCollection , TreeNodeCollection , CookieCollection , etc.) that I need to pass to a method that only accepts an array or list (shouldn't have a method that accepts a TreeNodeCollection in a TreeView , for example?) I need to write a method extensions as follows:

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

Or loop through the entire collection, adding items to the output list, and then converting the output list to an array:

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

So my question is: I often need these extension methods. It can allocate a lot of memory if the list is large, as usual. Why can't I get a link (and not a copy) to the internal array used by these *Collection classes so that I do not need to use these extensions and perform these memory allocations? or even provide a ToArray() method. We do not need to know its internal implementation or array used in the latter case.

+6
source share
1 answer

The reason that all classes in the BCL collection hide their internal array is due to the "usability of the API." An internal array can change if it needs to grow or shrink. Then any user code that has a link to the old array can get confused. In addition, user code can access array indices that are not valid for accessing the collection. If you have a List with Capacity = 16 && Count == 10 , then you can access the internal array with index 15, which normally would not allow the list.

These problems make it difficult to use the API. They raise support requests and questions.

Delete the existing code and replace it with:

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

You can do this in the extension method if you think it is necessary. Enter the IEnumerable parameter (no generics). It's a mystery to me why the existing collections in BCL have not been updated to implement IEnumerable<T> . For this you need Case . I just created a User Voice element for this.

+10
source

Source: https://habr.com/ru/post/985029/


All Articles