newnew

最佳答案:

newnewnew Guid()new Guid(someString)new(...)
Guid localVariable = new Guid(someString);

与用于以下目的的IL不同:
myInstanceOrStaticVariable = new Guid(someString);

此外,如果该值用作中间值,例如方法调用的参数,则情况会再次略有不同。为了显示所有这些差异,这里有一个简短的测试程序。它没有显示静态变量和实例变量之间的区别:IL在
stfld
stsfld
之间会有所不同,但仅此而已。
using System;

public class Test
{
    static Guid field;

    static void Main() {}
    static void MethodTakingGuid(Guid guid) {}


    static void ParameterisedCtorAssignToField()
    {
        field = new Guid("");
    }

    static void ParameterisedCtorAssignToLocal()
    {
        Guid local = new Guid("");
        // Force the value to be used
        local.ToString();
    }

    static void ParameterisedCtorCallMethod()
    {
        MethodTakingGuid(new Guid(""));
    }

    static void ParameterlessCtorAssignToField()
    {
        field = new Guid();
    }

    static void ParameterlessCtorAssignToLocal()
    {
        Guid local = new Guid();
        // Force the value to be used
        local.ToString();
    }

    static void ParameterlessCtorCallMethod()
    {
        MethodTakingGuid(new Guid());
    }
}

这是该类的IL,不包括不相关的位(如nops):
.class public auto ansi beforefieldinit Test extends [mscorlib]System.Object    
{
    // Removed Test's constructor, Main, and MethodTakingGuid.

    .method private hidebysig static void ParameterisedCtorAssignToField() cil managed
    {
        .maxstack 8
        L_0001: ldstr ""
        L_0006: newobj instance void [mscorlib]System.Guid::.ctor(string)
        L_000b: stsfld valuetype [mscorlib]System.Guid Test::field
        L_0010: ret     
    }

    .method private hidebysig static void ParameterisedCtorAssignToLocal() cil managed
    {
        .maxstack 2
        .locals init ([0] valuetype [mscorlib]System.Guid guid)    
        L_0001: ldloca.s guid    
        L_0003: ldstr ""    
        L_0008: call instance void [mscorlib]System.Guid::.ctor(string)    
        // Removed ToString() call
        L_001c: ret
    }

    .method private hidebysig static void ParameterisedCtorCallMethod() cil  managed    
    {   
        .maxstack 8
        L_0001: ldstr ""
        L_0006: newobj instance void [mscorlib]System.Guid::.ctor(string)
        L_000b: call void Test::MethodTakingGuid(valuetype [mscorlib]System.Guid)
        L_0011: ret     
    }

    .method private hidebysig static void ParameterlessCtorAssignToField() cil managed
    {
        .maxstack 8
        L_0001: ldsflda valuetype [mscorlib]System.Guid Test::field
        L_0006: initobj [mscorlib]System.Guid
        L_000c: ret 
    }

    .method private hidebysig static void ParameterlessCtorAssignToLocal() cil managed
    {
        .maxstack 1
        .locals init ([0] valuetype [mscorlib]System.Guid guid)
        L_0001: ldloca.s guid
        L_0003: initobj [mscorlib]System.Guid
        // Removed ToString() call
        L_0017: ret 
    }

    .method private hidebysig static void ParameterlessCtorCallMethod() cil managed
    {
        .maxstack 1
        .locals init ([0] valuetype [mscorlib]System.Guid guid)    
        L_0001: ldloca.s guid
        L_0003: initobj [mscorlib]System.Guid
        L_0009: ldloc.0 
        L_000a: call void Test::MethodTakingGuid(valuetype [mscorlib]System.Guid)
        L_0010: ret 
    }

    .field private static valuetype [mscorlib]System.Guid field
}

如您所见,调用构造函数时使用了许多不同的指令:
newobj
:在堆栈上分配值,调用参数化构造函数。用于中间值,例如用于字段赋值或用作方法参数。
call instance
:使用已分配的存储位置(无论是否在堆栈上)。这在上面的代码中用于分配给局部变量。如果同一个局部变量使用多个
new
调用多次赋值,它只会在旧值的顶部初始化数据-每次都不会分配更多的堆栈空间。
initobj
:使用已分配的存储位置,只擦除数据。这用于我们所有的无参数构造函数调用,包括那些分配给局部变量的调用。对于方法调用,有效地引入了一个中间局部变量,其值被
initobj
擦除。
我希望这能说明这个话题有多复杂,同时也能给它一点启发。在某些概念意义上,对
new
的每次调用都会在堆栈上分配空间——但正如我们所看到的,即使在IL级别,也不会真正发生这种情况。我想强调一个特殊的案例。采用这种方法:
void HowManyStackAllocations()
{
    Guid guid = new Guid();
    // [...] Use guid
    guid = new Guid(someBytes);
    // [...] Use guid
    guid = new Guid(someString);
    // [...] Use guid
}

这个“逻辑上”有4个堆栈分配-一个用于变量,一个用于三个
new
调用中的每一个-但实际上(对于特定代码),堆栈只分配一次,然后重用相同的存储位置。
编辑:为了清楚起见,这只在某些情况下是正确的…特别是,如果
guid
构造函数引发异常,则
Guid
的值将不可见,这就是为什么C编译器能够重用同一堆栈槽的原因。请参阅Eric Lippert'sblog post on value type construction了解更多详细信息和不适用的案例。
我在写这个答案时学到了很多东西——如果有任何不清楚的地方,请要求澄清!