33

当我resize(int newsize)在 C++ 中使用 forvector<T>时,这意味着sizethisvector设置为newsize并且索引在 range 中运行[0..newsize)。如何在 C# for 中做同样的事情List<T>
更改List<T>属性Capacity只会更改Capacity但保持Count不变,此外索引仍在范围内[0..Count)。请帮帮我。

PS想象一下我有vector<T> tmp一个tmp.size() == 5我无法引用的tmp[9],但是当我使用时tmp.resize(10)我可能会引用tmp[9]。在 C# 中,如果我有List<T> tmpwithtmp.Count == 5我不能引用tmp[9]( IndexOutOfRangeException),但即使我设置了tmp.Capacity=10我也无法引用tmp[9]coz oftmp.Count仍然是 5。我想在 C# 中找到一些 resize 的类比。

4

7 回答 7

35

不,但您可以使用扩展方法添加您自己的。以下具有与 相同的行为std::vector<T>::resize(),包括相同的时间复杂度。唯一的区别是,在 C++ 中,我们可以定义一个默认值,void resize ( size_type sz, T c = T() )模板的工作方式意味着如果我们在T没有可访问的无参数构造函数的 a 的默认值的情况下调用它,那很好。在 C# 中我们不能这样做,因此我们必须创建一个没有与非默认使用情况匹配的约束的方法,以及另一个具有where new()调用它的约束的方法。

public static class ListExtra
{
    public static void Resize<T>(this List<T> list, int sz, T c)
    {
        int cur = list.Count;
        if(sz < cur)
            list.RemoveRange(sz, cur - sz);
        else if(sz > cur)
        {
            if(sz > list.Capacity)//this bit is purely an optimisation, to avoid multiple automatic capacity changes.
              list.Capacity = sz;
            list.AddRange(Enumerable.Repeat(c, sz - cur));
        }
    }
    public static void Resize<T>(this List<T> list, int sz) where T : new()
    {
        Resize(list, sz, new T());
    }
}

现在,myList.Resize(23)myList.Resize(23, myDefaultValue)将符合人们对 C++ 向量的期望。我会注意到,有时在 C++ 中你会有一个指针向量,在 C# 中你会有一个引用类型的列表。因此,在 C++T()生成空指针(因为它是指针)的情况下,我们期望它调用无参数构造函数。出于这个原因,您可能会发现它更接近您习惯用以下方法替换第二种方法的行为:

  public static void Resize<T>(this List<T> list, int sz)
  {
      Resize(list, sz, default(T));
  }

这与值类型(调用无参数构造函数)具有相同的效果,但对于引用类型,它将填充空值。在这种情况下,我们可以将整个类重写为:

public static class ListExtra
{
    public static void Resize<T>(this List<T> list, int sz, T c = default(T))
    {
        int cur = list.Count;
        if(sz < cur)
            list.RemoveRange(sz, cur - sz);
        else if(sz > cur)
            list.AddRange(Enumerable.Repeat(c, sz - cur));
    }
}

请注意,这与其说是关于 C++ 和 C# 中指针使用方式之间的差异std::vector<T>,不如说是关于指针使用方式的差异。List<T>

于 2012-09-01T23:10:33.433 回答
17

只是为了让乔恩汉娜的答案更具可读性:

public static class ListExtras
{
    //    list: List<T> to resize
    //    size: desired new size
    // element: default value to insert

    public static void Resize<T>(this List<T> list, int size, T element = default(T))
    {
        int count = list.Count;

        if (size < count)
        {
            list.RemoveRange(size, count - size);
        }
        else if (size > count)
        {
            if (size > list.Capacity)   // Optimization
                list.Capacity = size;

            list.AddRange(Enumerable.Repeat(element, size - count));
        }
    }
}
于 2014-07-28T02:51:39.880 回答
0

设置List<T>.Capacity就像使用std::vector<T>.reserve(..). 也许List<T>.AddRange(..)适合您的需求。

于 2012-09-01T21:33:42.240 回答
0

对不起。这是你需要的吗? List.TrimExcess()

于 2012-09-01T21:36:08.040 回答
0

这是我的解决方案。

private void listResize<T>(List<T> list, int size)
{
   if (size > list.Count)
      while (size - list.Count > 0)
         list.Add(default<T>);    
   else if (size < list.Count)
      while (list.Count - size > 0)
         list.RemoveAt(list.Count-1);
}

sizelist.Count相同时,无需调整列表大小。

default(T)参数用于代替null""0其他可为空的类型来填充列表中的空项,因为我们不知道类型<T>是什么(引用、值、结构等)。

PS我使用for循环而不是while循环,我遇到了问题。列表的大小并不总是我要求的。它更小。有什么想法为什么?

核实:

private void listResize<T>(List<T> list, int size)
{
   if (size > list.Count)
      for (int i = 0; i <= size - list.Count; i++)
         list.Add(default(T));
   else if (size < list.Count)
      for (int i = 0; i <= list.Count - size; i++)
         list.RemoveAt(list.Count-1);
}
于 2014-05-28T06:40:10.173 回答
-2

你没有在 MSDN 上阅读过:-

列表是可调整大小的项目集合。列表可以通过多种方式构建,但最有用的类是 List。这允许您强烈键入您的列表,包括处理集合的所有基本功能,并且可以轻松搜索。

更远:-

容量 是在需要调整大小之前 List 可以存储的元素数,而 Count 是实际在 List 中的元素数。

容量始终大于或等于 Count。如果在添加元素时 Count 超过了容量,则通过在复制旧元素和添加新元素之前自动重新分配内部数组来增加容量

于 2012-09-01T21:37:59.943 回答
-7

列表没有有限的大小。

尺寸对您很重要有什么原因吗?

也许数组或字典更接近您的要求

于 2012-09-01T21:33:24.713 回答