batwadi
batwadi

Reputation: 1906

Creating objects in Loop C#

Just was curious about below code.

for (int i=0; i<9; i++)
{
   ClassA objectA = new ClassA();
}

or

ClassA objectA;
for (int i=0; i<9; i++)
{
    objectA = new ClassA();
}

Any Idea is there any difference for both code ? from my knowledge both will create different instances each time so number of instances are going to same .. Any idea ?

Upvotes: 6

Views: 14262

Answers (9)

Jojo Sardez
Jojo Sardez

Reputation: 8558

The number of instance is not incremented based on the codes. Both loops are just re-initializing a same variable the only difference is that on the first loop the instance variable is not accessible when it finishes the loop unlike on the second loop wherein the variable is declared outside the loop.

Upvotes: 2

Bruno Brant
Bruno Brant

Reputation: 8554

prakash, just for the sake of correctness/completeness: it's untrue that the variables won't be able to be accessed after the loop ends. We are usually assuming that the object being created is very simple, which might not be the case. For example, you can add the object to a global list inside the constructor, so all the objects are still accessible after the loop ends.

The relevant difference is the one pointed out by kbrinley, because you cannot use the variable (which is a object reference) outside the for scope (whatever is between { and }) on the first example. Since on the second one you declare the variable outside the loop, you can still use the variable.

As Marc Gravell said, the IL generated is the same for both, so there should be no difference in terms of performance, memory occupation, etc., for the loop.[1]


1: Since on the second example certainly retain a reference to the last variable, the Garbage Collector won't be able to free its space. So, after the loop ends, there will be subtle differences.

Upvotes: 0

Marc Gravell
Marc Gravell

Reputation: 1062600

Scoping aside (i.e. whether the variable exists outside of the loop) there is usually no difference, since .NET variables are actually (in the IL) all at the start of the method anyway. However, there is an exception: if you capture the variable (into an anonymous method / lambda), then it behaves differently - the capture is constructed to respect the C# declaration. So:

List<Action> actions = new List<Action>();
ClassA objectA;
for (int i=0;i<9;i++)
{
    objectA= new ClassA();
    actions.Add(delegate { Console.WriteLine(objectA.GetHashCode()); });        
}
foreach(Action action in actions) action();

and:

List<Action> actions = new List<Action>();
for (int i=0;i<9;i++)
{
    ClassA  objectA= new ClassA();
    actions.Add(delegate { Console.WriteLine(objectA.GetHashCode()); });        
}
foreach(Action action in actions) action();

Will do different things (the first prints the same address-based hash-code 9 times; the second prints 9 different address-based hash-codes, indicating that in the second loop we've captured 9 different variables, instead of a single variable).

In both cases there are 9 ClassA objects created - simply that we can't see 8 of them any more in the first case.

Upvotes: 25

kbrinley
kbrinley

Reputation: 3444

In the first snippet, objectA will not be accessible outside of the loop. Thus, if you wrote:

for (int i=0;i<9;i++) 
{ 
    ClassA objectA = new ClassA(); 
}
// This will not compile.
objectA.DoSomething();

You would receive a compile error. However, if you wrote the code as:

ClassA objectA; 
for (int i=0;i<9;i++) 
{ 
    objectA= new ClassA(); 
}
// This will compile.
objectA.DoSomething();

The second code snippet will compile (assuming ClassA has a method named DoSomething()).

Upvotes: 1

David Pfeffer
David Pfeffer

Reputation: 39833

Actually, since you never save a reference to your objects that you create, each time you override objectA, you will have eliminated the previous example.

However, in the case of:

for (int i=0;i<9;i++)
{
   ClassA objectA = new ClassA();
}

objectA does not exist outside of the scope of the loop, and all of the objects you created will eventually be deleted by the garbage collector. It would be a syntax error to reference objectA outside of the loop.

In contrast, in the case of:

ClassA objectA;
for (int i=0;i<9;i++)
{
    objectA= new ClassA();
}

objectA is a valid identifier outside of the loop, and the final instance of ClassA created will remain after the loop is completed.

Upvotes: 2

Miollnyr
Miollnyr

Reputation: 269

The only difference is that objectA will point to an ClassA example after second loop. In both cases 9 objects will be created, but in first case all of them will be destroyed, and in second one - the last object will not.

Upvotes: 0

Nick
Nick

Reputation: 5945

The difference between the two is that after the for loop completes, the instance of ClassA from the last iteration (i=8) will be available to the rest of the function, while in the first version, it won't be.

Upvotes: 0

John Knoeller
John Knoeller

Reputation: 34128

The only difference is that in the second example, the last created instance will still be accessible after the loop

Upvotes: 13

Gabe
Gabe

Reputation: 86708

The big difference is if you create a closure inside the loop that captures objectA, and that closure escapes the loop. In other words, if objectA is somehow visible outside the loop, then the first instance will have 9 different values after the loop ends, while the second one will only have the last value once the loop ends.

For example,

for (int i = 0; i < 9; i++)
{
    ClassA objectA = new ClassA();
    someFunc(() => objectA);
}

could have different visible results than

ClassA objectA;
for (int i = 0; i < 9; i++)
{
    objectA = new ClassA();
    someFunc(() => objectA);
}

Upvotes: 0

Related Questions