6

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 ?

9 Answers 9

25

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.

Sign up to request clarification or add additional context in comments.

1 Comment

As usual Marc, you deliver beyond expectation. Scope when doing lambda is a tough nut to crack sometimes. I'm sure we've all been burned by the scoping problem you point out above. I know I have. Cheers!
13

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

Comments

2

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.

Comments

2

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.

Comments

1

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()).

Comments

0

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);
}

2 Comments

Why do you specifically highlight closures here? someFunc(objectA) could also be saving a reference to each object, for example, if someFunc is a Collection's Add function.
someFunc(objectA) will pass a reference to a different object each iteration through the loop; someFunc(() => objectA) will pass either the same or different reference depending on where ClassA is declared.
0

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.

Comments

0

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.