1

int number = new int();

Questions:

  1. For reference types, the new operator creates an instance of the type by allocating memory on the heap then initializes it by calling the type's constructor. As seen above, you could do the same for a value type. To me, the line above means that the constructor int() is called to initialize number with a value. I have read that int is a keyword pointing to the struct System.Int32. Therefore, in Visual Studio, I navigate to the struct Int32. Lo and behold, no constructor exists. How exactly is this predefined type initialized to 0 without a constructor?

  2. Related to the above, is there a field in the Int32 struct that stores the value?

  3. Both for custom structs and classes I can create new instances with the new keyword, without the struct or class actually containing a constructor. In that case, is no initialization done at all of the fields the struct/class contains? Is the only thing that happens that memory is allocated on stack/heap for the value/reference type?

  4. Finally, for value types, no new keyword is needed for instantiation and initialization. How exactly does that work on a lower level? Say we do int number = 5;. Is it somehow translated to int a = new int(); a = 5;? If so, how?

Thanks a million!

carlpett
  • 12,203
  • 5
  • 48
  • 82
Magnus
  • 6,791
  • 8
  • 53
  • 84
  • 1
    1) [What does the keyword “new” does to a struct in C#?](http://stackoverflow.com/questions/9207488/what-does-the-keyword-new-does-to-a-struct-in-c) 4) [Where and why use int a=new int?](http://stackoverflow.com/questions/5746873/where-and-why-use-int-a-new-int) – Soner Gönül Aug 22 '14 at 14:37
  • 2) [Of course it does](http://referencesource.microsoft.com/#mscorlib/system/int32.cs) 3) There is [default constructor](http://msdn.microsoft.com/en-us/library/ms173115(v=vs.110).aspx) in place, when you didn't specify constructor in the code. – Michael Aug 22 '14 at 14:45
  • 3
    It is all just smoke and mirrors. The C# compiler, jitter and CLR have intimate built-in knowledge about the way value types work. They optimize the dickens out of them. Important to make code fast, value types exist because they are a good match with the way the processor works. Learning more about processors and machine code is the way to truly grok value types. – Hans Passant Aug 22 '14 at 14:46

2 Answers2

2

no constructor [of System.Int32] exists.

All value types have a default constructor:

Each value type has an implicit default constructor that initializes the default value of that type.

(end of quote)

Related to the above, is there a field in the Int32 struct that stores the value?

Yes, it does:

[Serializable]
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)] 
[System.Runtime.InteropServices.ComVisible(true)]
    public struct Int32 : IComparable, IFormattable, IConvertible
        , IComparable<Int32>, IEquatable<Int32>
        , IArithmetic<Int32> {
        internal int m_value; // <<== Here it is

        public const int MaxValue = 0x7fffffff;
        public const int MinValue = unchecked((int)0x80000000);
        ...
}

Both for custom structs and classes I can create new instances with the new keyword, without the struct or class actually containing a constructor.

That is not entirely correct: unlike structs, not all classes have an implicit default constructor; if you define a constructor that takes parameters, the compiler removes the default constructor from your class.

In that case, is no initialization done at all of the fields the struct/class contains?

All of the fields that are not initialized explicitly are set to their default values.

Say we do int number = 5;. Is it somehow translated to int a = new int(); a = 5;?

int is a built-in type. The compiler knows how to generate IL for it. The type of int is "baked into" the CIL the compiler generates for the assignment:

.locals init ([0] int32 a)
ldc.i4.s   5
stloc.0

The first line corresponds to the declaration of int a, with or without new. The last two lines do the assignment: load the value of 5 into a register, and store it in the local variable a (at index zero).

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • @Servy For q1 and q3 I now understand that the compiler creates a constructor if one does not exist, and (in the case of value types) uses it to assign a default value. On q2 I wonder why the implementation I have of Int32 in VS2013 differs from the link michael moore posted above. On q4 I still have no clue how it is possible to not use new for value types. Could I bother you to write up an answer to each? – Magnus Aug 22 '14 at 15:24
  • @Magnus I am not sure what implementation you have. The one linked by michael moore looks OK. I added it to the answer. – Sergey Kalinichenko Aug 22 '14 at 15:35
  • 1) When I click go to source on int() in VS2013, I see a class containing MaxValue, MinValue, as well as the various methods, only. No internal int m_value at all. 2) On the last point, does int a = 5; get changed to int a = new int(); a.m_value = 5; though? 3) By implicit constructor you mean that the compiler creates one for us, right? – Magnus Aug 22 '14 at 15:47
  • @Magnus When you go to source, the info is generated from metadata (at least that's what I see in my VS: it says "Int32 [from metadata]"). The code does not use `m_value` at all - the compiler has built-in logic to produce code for `Int32`s as a primitive data type. As you can see from the IL in my last example, there is no mention of `m_value` at all. It's also not there in the metadata because of this special handling. Same applies to other primitive value types. – Sergey Kalinichenko Aug 22 '14 at 15:52
-3
  1. Even if constructor is not defined, the compiler generates default constructor that initialize the value. Having said that, we should not rely on default constructor to initialize. I think default constructor MyObject() and copy constructor MyObject(MyObject second) are created automatically if it is not explicitly defined.

  2. I have not personally looked into Int32 struct but it should have a member that hold the value.

  3. As mentioned, when default constructor is not defined, they are automatically created so some initialization is done. Having said that, it is not a good practice to rely on auto created constructor to do the initialization.

  4. primitive types do not need and cannot use new keyword (unless when creating an array). When you use new keyword, it seems like int gets "converted" to Int32 which is a class and not a primitive. So, int number = 5 is just that. int a = new int(5) is translated into int a = (int)new Int32(5) This is called boxing. Some operation/collections cannot use primitive types directly, so when primitives are used for such situations, compiler automatically box the primitive types. If it is not needed, no need to box them but use them as primitive i.e.) don't new them.

Robert
  • 1
  • 2
    4 is just all wrong, in entirety. There is no implicitly created copy constructors, and there is nothing at all wrong with using the implicitly created constructors. Unlike languages such as C++, they actually have well defined behaviors (they zero out all bits representing that object's state). – Servy Aug 22 '14 at 14:58
  • About copy construct yes. However, I respectfully disagree on relying implicit default constructor. See: http://stackoverflow.com/questions/2963742/empty-constructor-or-no-constructor – Robert Aug 22 '14 at 15:05
  • 1
    That scenario is both contrived, trivially avoided, and will be noticed with even the most trivial of testing of an application. Not using the feature ever for only that reason isn't sensible at all. Your assertions that the default constructor is somehow "unreliable" or that the generally accepted practice is not to use it are both entirely wrong. Additionally, this is about value types, not reference types, for which there's no way to *not* have a default constructor. You couldn't remove it if you *tried*. – Servy Aug 22 '14 at 15:10