-1

Adding primitive struct (eg. int) to a List:

int i=10;
List<int> list=new List<int>();
list.Add(i);

Versus: Adding non-primitive struct (eg. KeyValuePair<int,int>) to a list:

List<KeyValuePair<int, int>> list = new List<KeyValuePair<int, int>>();
list.Add(new KeyValuePair<int,int>(10,20));

While adding the int struct to a list, we do not need to use the new keyword. But while adding the KeyValuePair struct to a list, we need to use the new keyword.

I mean to say, the following statement is not valid:

list.Add(new int(10)); //invalid statement

Though both int and KeyValuePair are struct's, they behave differently - one does not require instantiation before use (as far as the user is concerned). And the other requires instantiation before use.

Why can't we do the following instead:

list.Add(KeyValuePair<int,int>(10,20)) //omit the new keyword, as we were doing with an int

Coming from a C/C++ background, what does the new keyword exactly do in C#? Does it just instantiate the underlying data type (and we are not sure whether the instantiated data type will lie on the Stack or the Heap). Or, are we sure that using the new keyword will allocate memory on the Heap (as it does in C++)?

Vikram Singh
  • 435
  • 2
  • 10
  • 1
    Read my answer to this question https://stackoverflow.com/questions/65418824/object-passing-reference-vs-value/65419301#65419301. It doesn't directly answer your question, but it should make the answer obvious – Flydog57 Dec 25 '20 at 04:45
  • _"While adding the int struct to a list, we do not need to use the new keyword. But while adding the KeyValuePair struct to a list, we need to use the new keyword"_ -- That is completely false. Fundamentally, your question is broken. The examples you claim as somehow fundamentally different, aren't different at all. It's true that `System.Int32` doesn't have any constructor with a parameter. But you can certainly write `new int()`. ... – Peter Duniho Dec 25 '20 at 04:47
  • ... More to the point, you can also name a variable `i`, declaring it as `KeyValuePair`, and then add to the list **using the exact same syntax as in the first example**, i.e. `list.Add(i);`. **There is no difference, and so asking why there is a difference makes no sense whatsoever.** – Peter Duniho Dec 25 '20 at 04:48
  • For additional information, other than the obvious of **reading the language documentation**, you can also see Stack Overflows questions https://stackoverflow.com/questions/9207488/what-does-the-keyword-new-do-to-a-struct-in-c and https://stackoverflow.com/questions/11504910/what-does-the-new-keyword-in-net-actually-do – Peter Duniho Dec 25 '20 at 04:50
  • 2
    And, for what it's worth, when a type has a *literal* representation, you can think of the literal as a 'const' version of `new T (LiteralOfT)`. An expression like `int i = 10;` is very close to `int i = new int(10)`. The `new` keyword allocates memory off the managed heap and then runs a constuctor for reference types, just like C++. The `new` keyword for value types simply runs the constructor and does not allocate memory. The result of the constructed object is then value copied into the variable – Flydog57 Dec 25 '20 at 04:53
  • 2
    The question is interesting even if badly written. Why can you initialize certain types (`int`, `string`, ...) without using `new` (or `default()`) keywords? And the answer boils down to the existance of literals (and constant expressions (you can do `int x = (int)5.5`)) – xanatos Dec 25 '20 at 08:39

1 Answers1

1

what does the new keyword exactly do in C#?

It's all listed here. The most relevant one to this question is "constructor invocation". Structs and classes have constructors, and constructors create instances of structs and classes.

When you do:

new KeyValuePair<int,int>(10,20)

you are calling this constructor.

int, which is an alias for the Int32 struct, does not have a constructor that accepts a parameter of type int. This is the reason why you can't do:

new int(10)

Note that calling a constructor isn't the only way to create an instance of a struct. You can also do something like:

var defaultKVP = default(KeyValuePair<int, int>); // gets the default value of the type KeyValuePair<int, int>
// defaultKVP is an instance of KeyValuePair<int, int>! It's not null! Structs can't be null :)

The default value of a struct is defined by setting all its value-typed fields to their default values, and reference-typed fields to null.

The reason why an integer literal like 10 is an instance of the struct Int32, is, well, compiler magic. The spec says so, so it is implemented this way.

Sweeper
  • 213,210
  • 22
  • 193
  • 313