简体   繁体   English

这两个声明有什么区别

[英]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 第二种方法如何获得其对象引用

The latter form is syntactical sugar and is called "Collection Initializers" . 后一种形式是语法糖,称为“集合初始化器” Under the covers, the compiler looks for an Add method. 在幕后,编译器将查找Add方法。 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. 集合初始化器可让您在初始化实现IEnumerable的集合类或带有Add扩展方法的类时指定一个或多个元素初始化器。

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: 您可以在生成的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

The only difference between the codes is that the variable lt has a name in the first example. 这两个代码之间的唯一区别是,在第一个示例中,变量lt具有名称。 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. 与第一个示例一样,初始化列表将变成对Add调用。

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: 为第一个示例生成的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>)

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. 唯一的区别是第一个具有变量名lt而第二个具有编译器生成的名称'<>g__initLocal6'

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. 如果数据在不同情况下动态出现,则使用方法2或数据是静态的,则使用方法1。

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. 如果已经定义了项目,则可以使用构造函数初始化程序,或者如果需要动态添加项目,则可以使用Add方法。 This post will give you better idea. 这篇文章会给你更好的主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM