Reputation: 3733
I was wondering if it is safe to create new objects as part of a method (or indeed constructor call)
Such as the convuluted example below:
public class Igloo
{
public int i = 5;
}
public class Program
{
static void Main(string[] args)
{
DoSomething(new Igloo());
}
private static void DoSomething(Igloo i)
{
Debug.WriteLine(i.i);
}
}
Is creating temporary objects like this frowned upon? Does the new object that is created get cleaned up properly.
Upvotes: 2
Views: 5756
Reputation: 86729
SLaks is right - this is completely fine and is for all intents and purposes identical to doing the following:
Igloo igloo = new Igloo();
DoSomething(igloo);
In both cases as soon as the Igloo
instance is passed to the DoSomething
method - at this point the instance is no longer accessible from within the Main
method making the instance elegible for collection once the DoSomething
method has finished with it.
If we want to take a look at whats going on in more detail then take a peek at the IL:
.method private hidebysig static
void Main (string[] args) cil managed
{
// Method begins at RVA 0x2060
// Code size 13 (0xd)
.maxstack 8
.entrypoint
IL_0000: nop
IL_0001: newobj instance void ConsoleApplication1.Igloo::.ctor()
IL_0006: call void ConsoleApplication1.Program::DoSomething(class ConsoleApplication1.Igloo)
IL_000b: nop
IL_000c: ret
}
To explain what this means; We see that on IL_0001
that we create a new instance of Igloo
- as the CLR is a stack based virtual machine this instruction pushes a reference to that instance onto the stack. The next instruction is the call to DoSomething
- again the CLR is a stack based virtual machine and so arguments are pushed onto the stack from left to right (so that the last item on the stack is the right-most argument). In this case there is only 1 argument and its already on the stack as a result of the last operation and so we are ready to call our method.
If we compare this to the IL produced when we make the following modification:
Igloo igloo = new Igloo();
DoSomething(igloo);
We can see only a couple of important differences:
.method private hidebysig static
void Main (string[] args) cil managed
{
// Method begins at RVA 0x2060
// Code size 15 (0xf)
.maxstack 1
.entrypoint
.locals init (
[0] class ConsoleApplication1.Igloo igloo
)
IL_0000: nop
IL_0001: newobj instance void ConsoleApplication1.Igloo::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: call void ConsoleApplication1.Program::DoSomething(class ConsoleApplication1.Igloo)
IL_000d: nop
IL_000e: ret
}
Aside from at the start of the method where locals are declared the only difference is the stloc.0
and ldloc.0
calls in between creating Igloo
and our call to DoSomething
. What is this?
stloc.0
is an instruction to pop the last item off the stack and store it in the 0th local. Note at this point we no longer have the correct stack to call DoSomething
(we need our Igloo
instance to be at the top of the stack) this is what ldloc.0
is for - it pushes the 0th local (back) on to the stack. Essentially these two instructions are our assignment.
Note that when this gets compiled down to machine code by the JITer these two statements will almost certainly get optimised out.
Upvotes: 3
Reputation: 45071
If you create a Windows Form project instead of a console one, you'll find the following line in the program.cs:
Application.Run(new FormMain());
So it seems that MS also does exactly the same as default for a windows forms project.
Upvotes: 3
Reputation: 8245
Yes, that is ok. The object will be automatically deleted later.
Upvotes: 1
Reputation: 25495
This is safe and standard in c# all the garbage collector will collect those objects once they become unreachable.
Upvotes: 1
Reputation: 887225
There is nothing wrong with that.
In release mode, creating a variable for the object should end up compiling to the same IL (disclaimer: I haven't checked).
Upvotes: 6