在 C# 中是否有用于列表的方法<T>,例如在 C++ 中为矢量<T>调整大小

is there in C# a method for List<T> like resize in c++ for vector<T>

本文关键字:gt lt C++ 调整 列表 方法 用于 是否      更新时间:2023-10-16

当我在C++中将resize(int newsize)用于vector<T>时,这意味着该vectorsize设置为newsize,并且索引在范围[0..newsize)中运行。如何在C#中对List<T>执行同样的操作
更改List<T>属性Capacity仅更改Capacity,但保持Count不变,而且索引仍在[0..Count)范围内。请帮帮我。

附言:假设我有一个带有tmp.size() == 5vector<T> tmp,我不能引用tmp[9],但当我使用tmp.resize(10)时,我可以引用tmp[9]。在C#中,如果我有List<T> tmptmp.Count == 5,我就不能引用tmp[9]IndexOutOfRangeException),但即使当我设置tmp.Capacity=10时,我也不能引用tmp[9],因为tmp.Count的值仍然是5。我想在C#中找到一些调整大小的相似之处。

否,但您可以使用扩展方法添加自己的方法。以下具有与std::vector<T>::resize()相同的行为,包括相同的时间复杂性。唯一的区别是,在C++中,我们可以用void resize ( size_type sz, T c = T() )定义一个默认值,而模板的工作方式意味着,如果我们为没有可访问的无参数构造函数的T调用它而不使用默认值,那也没关系。在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));
  }

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

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));
    }
}

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

只是为了让Jon Hanna的答案更易读:

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));
        }
    }
}

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

这是我的解决方案。

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或其他可为null的类型来填充列表中的空项,因为我们不知道<T>是什么类型(引用、值、结构等)。

附言:我使用了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);
}

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

你没有在MSDN上读过吗:-

列表是可调整大小的项目集合。可以构建列表有多种方法,但最有用的类是List。这允许您要强烈键入您的列表,请包括所有必需的处理集合的功能,并且可以很容易地已搜索。

进一步:-

Capacity是列表之前可以存储的元素数需要调整大小,而Count是实际上在列表中。

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

列表没有有限的大小。

尺寸对你来说重要是有原因的吗?

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