When I use resize(int newsize)
in C++ for vector
, it means that the size
of this vector
are set to newsize
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 size
and list.Count
are the same, there is no need to resize the list.
The default(T)
parameter is used instead of null
,""
,0
or other nullable types, to fill an empty item in the list, because we don't know what type <T>
is (reference, value, struct etc.).
P.S. I used
for
loops instead ofwhile
loops 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); }
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
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 T
that 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.
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:
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#.
Just to make Jon Hanna's answer more readable:
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));
}
}
}
sorry. is this what u need? List.TrimExcess()
Haven't you read at 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.
Further:-
Capacity is 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.