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中。
第二种方法如何获得其对象引用
答案 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会给你更好的主意。