Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

c#

list

vector

When I use resize(int newsize) in C++ for vector<T>, it means that the size of this vector are set to newsize and the indexes run in range [0..newsize). How to do the same in C# for List<T>?
Changing the List<T> property Capacity only changes the Capacity but leaves the Count the same, and furthermore the indexes still are in range [0..Count). Help me out, please.

P.S. Imagine I have a vector<T> tmp with a tmp.size() == 5 I 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> tmp with tmp.Count == 5 I cannot refer to tmp[9] (IndexOutOfRangeException), but even when I set tmp.Capacity=10 I will not be able to refer to tmp[9] coz of tmp.Count is still 5. I want to find some analogy of resize in C#.

like image 606
nhtrnm Avatar asked Sep 01 '12 21:09

nhtrnm


People also ask

Is there in operator in C?

C language supports a rich set of built-in operators. An operator is a special symbol that tells the compiler to perform specific mathematical or logical operations.

What is |= in C programming?

|= is shorthand for doing an OR operation and assignment. For example,, x |= 3 is equivalent to x = x | 3 . You can also use other operators ( +, -, *, & , etc) in this manner as well.


1 Answers

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#.

like image 175
Jon Hanna Avatar answered Sep 24 '22 09:09

Jon Hanna