在 C# 中是否有 List<T> 的方法,例如在 C++ 中为 vector<T> 调整大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12231569/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
is there in C# a method for List<T> like resize in c++ for vector<T>
提问by nhtrnm
When I use resize(int newsize)in C++ for vector<T>, it means that the sizeof this vectorare set to newsizeand the indexes run in range [0..newsize). How to do the same in C# for List<T>?
Changing the List<T>property Capacityonly changes the Capacitybut leaves the Countthe same, and furthermore the indexes still are in range [0..Count). Help me out, please.
当我resize(int newsize)在 C++ 中使用for 时vector<T>,这意味着sizethisvector被设置为newsize并且索引在 range 中运行[0..newsize)。如何在 C# 中做同样的事情List<T>?
更改List<T>属性Capacity只会更改Capacity但保持Count不变,而且索引仍在范围内[0..Count)。请帮帮我。
P.S. Imagine I have a vector<T> tmpwith a tmp.size() == 5I cannot refer to tmp[9], but when I then use tmp.resize(10)I may refer to tmp[9]. In C# if I have List<T> tmpwith tmp.Count == 5I cannot refer to tmp[9](IndexOutOfRangeException), but even when I set tmp.Capacity=10I will not be able to refer to tmp[9]coz of tmp.Countis still 5. I want to find some analogy of resize in C#.
PS想象我有vector<T> tmp一个tmp.size() == 5我不能引用tmp[9],但是当我然后使用tmp.resize(10)我可以引用tmp[9]。在C#如果我有List<T> tmp跟tmp.Count == 5我不是指tmp[9](IndexOutOfRangeException),但即使当我设置tmp.Capacity=10我将无法指tmp[9]堂妹的tmp.Count依然是5。我想找到C#调整大小的一些比喻。
采纳答案by Jon Hanna
No, but you can use extension methods to add your own. The following has the same behaviour as std::vector<T>::resize(), including the same time-complexity. The only difference is that in C++ we can define a default with void resize ( size_type sz, T c = T() )and the way templates work means that that's fine if we call it without the default for a Tthat has no accessible parameterless constructor. In C# we can't do that, so instead we have to create one method with no constraint that matches the non-default-used case, and another with a where new()constraint that calls into it.
不,但您可以使用扩展方法来添加自己的方法。以下与 具有相同的行为std::vector<T>::resize(),包括相同的时间复杂度。唯一的区别是,在 C++ 中,我们可以定义一个默认的 with void resize ( size_type sz, T c = T() ),模板的工作方式意味着,如果我们调用它而没有默认的 aT没有可访问的无参数构造函数,那也没关系。在 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());
}
}
Now the likes of myList.Resize(23)or myList.Resize(23, myDefaultValue)will match what one expects from C++'s vector. I'd note though that sometimes where with C++ you'd have a vector of pointers, in C# you'd have a list of some reference-type. Hence in cases where the C++ T()produces a null pointer (because it's a pointer), here we're expecting it to call a parameterless constructor. For that reason you might find it closer to the behaviour you're used to to replace the second method with:
现在,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));
}
This has the same effect with value types (call parameterless constructor), but with reference-types, it'll fill with nulls. In which case, we can just rewrite the entire class to:
这与值类型(调用无参数构造函数)具有相同的效果,但对于引用类型,它将用空值填充。在这种情况下,我们可以将整个类重写为:
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));
}
}
Note that this isn't so much about differences between std::vector<T>and List<T>as about the differences in how pointers are used in C++ and C#.
请注意,这与其说是关于 C++ 和 C# 中指针使用方式的差异std::vector<T>,List<T>不如说是关于它们之间的差异。
回答by podiluska
A list doesn't have a finite size.
列表没有有限的大小。
Is there a reason why the size matters to you?
有什么理由说明尺寸对您很重要吗?
Perhaps an array or a dictionary is closer to your requirements
也许数组或字典更接近您的要求
回答by Simon
Setting List<T>.Capacityis like using std::vector<T>.reserve(..). Maybe List<T>.AddRange(..)fit your needs.
设置List<T>.Capacity就像使用std::vector<T>.reserve(..). 也许List<T>.AddRange(..)适合你的需求。
回答by DarthVader
sorry. is this what u need? List.TrimExcess()
对不起。这是你需要的吗? List.TrimExcess()
回答by perilbrain
Haven't you read at MSDN:-
你有没有在 MSDN 上读过:-
A list is a resizable collection of items. Lists can be constructed multiple ways, but the most useful class is List. This allows you to strongly type your list, includes all of the essential functionality for dealing with collections, and can be easily searched.
列表是可调整大小的项目集合。列表可以通过多种方式构建,但最有用的类是 List。这允许您强输入您的列表,包括处理集合的所有基本功能,并且可以轻松搜索。
Further:-
更远:-
Capacityis the number of elements that the List can store before resizing is required, while Count is the number of elements that are actually in the List.
Capacity is always greater than or equal to Count. If Count exceeds Capacity while adding elements, the capacity is increased by automatically reallocating the internal array before copying the old elements and adding the new elements.
容量是在需要调整大小之前 List 可以存储的元素数量,而 Count 是实际在 List 中的元素数量。
容量总是大于或等于计数。如果在添加元素时 Count 超过 Capacity,则通过在复制旧元素和添加新元素之前自动重新分配内部数组来增加容量。
回答by Christos Karamoustos
This is my solution.
这是我的解决方案。
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);
}
When the sizeand list.Countare the same, there is no need to resize the list.
当size和list.Count相同时,无需调整列表大小。
The default(T)parameter is used instead of null,"",0or other nullable types, to fill an empty item in the list, because we don't know what type <T>is (reference, value, struct etc.).
该default(T)参数是用来代替null,"",0或其他可空类型,在列表中,以填补空白的项目,因为我们不知道是什么类型<T>的(参考,值,结构等)。
P.S. I used
forloops instead ofwhileloops and i ran into a problem. Not always the size of the list was that i was asking for. It was smaller. Any thoughts why?Check it:
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); }
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); }
回答by puradox
Just to make Jon Hanna's answermore readable:
只是为了让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));
}
}
}

