这两个声明之间有什么区别

时间:2015-09-12 12:02:13

标签: c#

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

现在我可以在下面的方法中调用上面的方法

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

test1.print(lt);

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

有人可以说明何时使用哪个?

问题在评论中有更多信息,因此需要更新以澄清:

ASK:
.First方法声明对象和内存将首先初始化,但第二种方法必须将所有内容存储在fly中。

第二种方法如何获得其对象引用

4 个答案:

答案 0 :(得分:2)

后一种形式是语法糖,称为"Collection Initializers"。在幕后,编译器会查找Add方法。如果提供,它将使用提供的元素调用所述方法,否则将显示编译时错误:

  

Collection初始化程序允许您在初始化实现IEnumerable的集合类或使用Add扩展方法的类时指定一个或多个元素初始值设定项。

唯一的区别是你的第一种方法保留了对列表的引用,这将允许你在以后需要时操作它。

  

仍然对第二种方法如何获得其对象感到困惑   参考

编译器将首先创建列表,然后仅以列表作为参数调用该方法。您可以在生成的IL中看到:

此:

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

的作用:

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

答案 1 :(得分:1)

代码之间的唯一区别是变量lt在第一个示例中有一个名称。除此之外,生成的代码是相同的。

第二个示例还将有一个变量,其中在初始化列表时存储引用,但变量由编译器使用,不会暴露给代码。初始化列表将变为对Add的调用,就像在第一个示例中一样。

因此,除了变量的可见性之外它们实际上是相同的,因此不存在性能差异等问题。您应该使用方便的表格。

第一个示例生成的IL代码是:

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

对于第二个例子:

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

唯一的区别是第一个具有变量名lt,而第二个具有编译器生成的名称'<>g__initLocal6'

答案 2 :(得分:1)

他们之间没有区别。关于您在列表中推送的数据的两个用法'差异。如果数据在不同场景中动态出现,则使用方法2或数据是静态的,然后使用方法1.

答案 3 :(得分:1)

两者都使用定义的项初始化列表。如果已经定义了项目,则可以使用构造函数初始化程序,或者如果需要动态添加项目,则可以使用Add方法。 This post会给你更好的主意。

相关问题