【问题标题】:Set/extend List<T> length in c#在 C# 中设置/扩展 List<T> 长度
【发布时间】:2009-01-26 22:14:36
【问题描述】:

给定 c# 中的 List&lt;T&gt;,有没有办法扩展它(在其能力范围内)并将新元素设置为 null?我想要像memset 这样的东西。我不是在这里寻找糖,我想要快速的代码。我知道在 C 中,操作可以在每个条目 1-3 个 asm 操作中完成。

我找到的最佳解决方案是this:

list.AddRange(Enumerable.Repeat(null, count-list.Count));

但是那是 c# 3.0(

我当前的代码使用:

while(list.Count < lim) list.Add(null);

这就是时间成本的起点。

motivation for this 是我需要设置第 n 个元素,即使它在旧计数之后。

【问题讨论】:

  • 如果这种情况经常发生,我建议使用 Dictionary 而不是 List

标签: c# list


【解决方案1】:

最简单的方法可能是创建一个临时数组:

list.AddRange(new T[size - count]);

其中size 是所需的新大小,count 是列表中的项目数。 但是,对于相对较大的 size - count 值,这可能会导致性能不佳,因为它会导致列表重新分配多次。(*) 它还有一个缺点是分配额外的临时数组,根据您的要求,这可能是不可接受的。您可以通过使用以下方法以牺牲更明确的代码为代价来缓解这两个问题:

public static class CollectionsUtil
{
    public static List<T> EnsureSize<T>(this List<T> list, int size)
    {
        return EnsureSize(list, size, default(T));
    }

    public static List<T> EnsureSize<T>(this List<T> list, int size, T value)
    {
        if (list == null) throw new ArgumentNullException("list");
        if (size < 0) throw new ArgumentOutOfRangeException("size");

        int count = list.Count;
        if (count < size)
        {
            int capacity = list.Capacity;
            if (capacity < size)
                list.Capacity = Math.Max(size, capacity * 2);

            while (count < size)
            {
                list.Add(value);
                ++count;
            }
        }

        return list;
    }
}

这里唯一的 C# 3.0 是使用“this”修饰符来使它们成为扩展方法。删除修饰符,它将在 C# 2.0 中工作。

很遗憾,我从来没有比较过两个版本的性能,所以不知道哪个更好。

哦,你知道你可以通过调用Array.Resize&lt;T&gt; 来调整数组的大小吗?我不知道。 :)

更新:
(*) 使用list.AddRange(array) 将不会导致使用枚举器。通过 Reflector 进一步观察,发现该数组将被强制转换为 ICollection&lt;T&gt;,并且将使用 Count 属性,以便只进行一次分配。

【讨论】:

  • “list.AddRange(new T[size - count]);”在评论中看起来不错。我想知道优化器是否可以避免枚举器。
  • @BCS,我错了,List&lt;T&gt;.AddRange 的实现实际上针对这种情况进行了优化。我已经更新了我的帖子。
【解决方案2】:
static IEnumerable<T> GetValues<T>(T value, int count) {
   for (int i = 0; i < count; ++i)
      yield return value;
}

list.AddRange(GetValues<object>(null, number_of_nulls_to_add));

这将适用于 2.0+

【讨论】:

  • 这样做的好处是它用所需的值填充列表。但是,如果空值或零就足够了,那么只需 list.AddRange(new T[count - list.Count] 就足够了。 (而且我猜它至少对于小数组大小会表现得更好。)
【解决方案3】:

你为什么要这样做? List 的主要优点是它可以根据需要增长,那么为什么要向它添加一些 null 或默认元素呢?

在这种情况下使用数组不是更好吗?

【讨论】:

  • IIRC 数组无法增长(您可以制作更大的副本但不能增长)
  • List 不是数组。它可以成长。
  • 确实,数组可以增长,但是当您想将列表设置为多个(空)元素时,使用列表有什么用呢?或者,我只是误解了这个问题吗?
  • 实际上数组可以增长!我不知道,但我只是注意到Array.Resize() 方法:msdn.microsoft.com/en-us/library/bb348051.aspx
  • Array.Resize() 不会改变数组的大小。它创建一个新数组并复制元素。
猜你喜欢
  • 2012-12-01
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-15
  • 1970-01-01
  • 2011-10-01
  • 1970-01-01
相关资源
最近更新 更多