TheGameiswar
TheGameiswar

Reputation: 28890

What is the difference between these two declarations

class test1
{
    // public  int a;
    public static void print(List<int> numbers)
    {
        int sum = 0;
        foreach(int number in numbers)
        {
            sum = sum + number;
        }
    }
}

now I can call above method in like below

List<int> lt = new List<int>();
lt.Add(1);
lt.Add(2);

test1.print(lt);

or

test1.print(new List<int> { 1, 23 });

Can some one shed some light on when to use which?

the question has more info in comments,so updated to clarify :

ASK:
.First method declares object and memory will be initialized first only,but second method has to store everything in fly.

how second method is able to get its object reference

Upvotes: 0

Views: 85

Answers (4)

Guffa
Guffa

Reputation: 700252

The only difference between the codes is that the variable lt has a name in the first example. Other than that the generated code is identical.

The second example will also have a variable where the reference is stored while the list is initialised, but the variable is used by the compiler and not exposed to the code. Initialising the list is turned into calls to Add, just as in the first example.

So, as they are actually identical except for the visibility of the variable, there are no concerns for performance difference or such. You should use the form that is convenient for whatever you are doing.


The generated IL code for the first example is:

.locals init (
    [0] class [mscorlib]System.Collections.Generic.List`1<int32> lt
)

IL_0000: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldc.i4.1
IL_0008: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
IL_000d: ldloc.0
IL_000e: ldc.i4.2
IL_000f: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
IL_0014: ldloc.0
IL_0015: call void TestConsole.Program/test1::print(class [mscorlib]System.Collections.Generic.List`1<int32>)

And for the second example:

.locals init (
    [0] class [mscorlib]System.Collections.Generic.List`1<int32> '<>g__initLocal6'
)

IL_0000: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldc.i4.1
IL_0008: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
IL_000d: ldloc.0
IL_000e: ldc.i4.2
IL_000f: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
IL_0014: ldloc.0
IL_0015: call void TestConsole.Program/test1::print(class [mscorlib]System.Collections.Generic.List`1<int32>)

The only difference is that the first has the variable name lt while the second has the name '<>g__initLocal6' generated by the compiler.

Upvotes: 1

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

The latter form is syntactical sugar and is called "Collection Initializers". Under the covers, the compiler looks for an Add method. If provided, it invokes the said method with the elements provided, otherwise a compile time error is shown:

Collection initializers let you specify one or more element initializers when you initialize a collection class that implements IEnumerable or a class with an Add extension method.

The only difference is that your first approach keeps a reference to the list, which will allow you to manipulate it later if needed.

Still confused on how second method is able to get its object reference

The compiler will first create the list, and only then invoke the method with the list as an argument. You can see that in the generated IL:

This:

public void X()
{
    M(new List<int> {3,4});
}
public void M(List<int> foo) 
{
}

Does:

IL_0002: newobj instance void class
         [mscorlib]System.Collections.Generic.List`1<int32>::.ctor() // Create the list
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: ldc.i4.3 // Load the number 3
IL_000a: callvirt instance void class 
         [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0) // Add it to the list
IL_000f: nop
IL_0010: ldloc.0
IL_0011: ldc.i4.4 // Load the number 4
IL_0012: callvirt instance void class
        [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0) // Add it to the list
IL_0017: nop
IL_0018: ldloc.0
IL_0019: call instance void C::M(class
         [mscorlib]System.Collections.Generic.List`1<int32>) // Invoke M with the list as an argument
IL_001e: nop
IL_001f: ret

Upvotes: 2

M_Idrees
M_Idrees

Reputation: 2172

Both initializes your list with the items defined. If you already have defined items you can use constructor initializer, or if you need to add items dynamically you can use Add method. This post will give you better idea.

Upvotes: 1

Erdem Şekerci
Erdem Şekerci

Reputation: 51

No difference between them. Two usage' differences about data you push in list. If The datas comes up dynamically in different scenarios, you use method 2 or datas is static then you use method 1.

Upvotes: 1

Related Questions