将集合转换为数组或列表的快速方法?

时间:2015-04-12 19:20:14

标签: c# arrays collections

对于我需要传递给只接受数组或列表的方法的每个*CollectionHtmlNodeCollectionTreeNodeCollectionCookieCollection等)类实例(不应该'有一个方法接受TreeView中的TreeNodeCollection吗?)我必须写一个这样的扩展方法:

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

或者遍历整个集合,将项目添加到输出列表,然后将输出列表转换为数组:

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

所以,我的问题是: 我经常需要这种扩展方法。如果列表很大,它可能会分配大量内存,通常是这样。为什么我不能只获取这个*Collection类使用的内部数组的引用(而不是复制),这样我就不需要使用那些扩展并执行这些内存分配了?甚至提供ToArray()方法。我们不需要知道它在最后一种情况下使用的内部实现或数组。

1 个答案:

答案 0 :(得分:12)

所有BCL集合类隐藏其内部数组的原因是出于“API niceness”的原因。内部阵列可以在需要增长或缩小的情况下进行更改。然后,任何引用旧数组的用户代码都会变得混乱。此外,用户代码可能会访问无法访问集合的数组索引。如果你有List Capacity = 16 && Count == 10,那么你可以访问列表通常不允许的索引为15的内部数组。

这些问题使API难以使用。它们会导致支持票证和Stack Overflow问题。

删除现有代码并将其替换为:

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

如果您觉得有必要,可以将其转换为扩展方法。输入参数IEnumerable(无泛型)。对我来说,为什么BCL中的现有集合尚未升级为实现IEnumerable<T>,这是一个谜。这就是你需要Case的原因。 I just created a User Voice item for this.