初始化对象与new和没有new之间有什么区别

时间:2016-12-29 14:00:45

标签: c# .net

这两个代码之间有什么区别:

MyClass a = new MyClass();
a = "something"

MyClass a = "something";

在第一个代码中,它创建了MyClass对象的新副本。 但是当不使用新关键字时会发生什么?它会影响初始类(MyClass)吗?

2 个答案:

答案 0 :(得分:8)

嗯,第二种形式是非法的,除非定义了转换运算符。

要实现此转化运算符,您必须使用new MyClass构建新实例。

因此,如果第二种形式是合法的,方法和最终结果是相同的。

转换运算符示例:

public class MyClass
{
    public static implicit operator MyClass(string s)
    {
        return new MyClass();
    }
}

请注意,此转化运算符也会处理此行:

a = "something";

其中只是用转换运算符返回的新引用覆盖a中存储的原始引用。

转换运算符定义了一个名为op_Implicit的静态方法(在本例中),这个方法将被调用,所以你的代码真的看起来像这样:

MyClass a = new MyClass();
a = MyClass.op_Implicit("something");

或者这个:

MyClass a = MyClass.op_Implicit("something");

如果您可以阅读LINQPad,则可以使用IL进行验证。

此代码:

void Main()
{
    MyClass a = "something";
    a = "xyz";
}

转换为此IL:

IL_0000:  nop         
IL_0001:  ldstr       "something"
IL_0006:  call        UserQuery+MyClass.op_Implicit
IL_000B:  stloc.0     // a
IL_000C:  ldstr       "xyz"
IL_0011:  call        UserQuery+MyClass.op_Implicit
IL_0016:  stloc.0     // a
IL_0017:  ret  

请注意对op_Implicit的两次调用。

现在,如果您没有实施转化运算符,那么:

MyClass a = new MyClass();
a = "something"                      // error

MyClass a = "something";             // error

错误信息在两种情况下均为:

  

CS0029
  无法隐式转换类型'字符串'到了MyClass'

答案 1 :(得分:0)

如果删除"something"周围的双引号,something是包含MyClass实例的变量的名称,则两者都有效。

即,如果代码是: 案例1:

MyClass something - new MyClass();
MyClass a = new MyClass();
a = something;   -- <--- This overwrites a with a different instance of 
                 --      MyClass, and leaves original instance in [a]
                 --      orphaned and subject to garbage collection.

或,案例2:

MyClass something - new MyClass();
MyClass a = something;

然后两个都很好。并且两种形式之间没有区别,除了在源代码中,一个在一个语句中表示,另一个在两个语句中。在这两种形式中,底层代码正在执行两个单独的操作,一个实例为MyClass的堆上的内存分配,以及一个指针变量(something)的创建和初始化,填充了该实例的地址。我不会惊讶地发现两者在基础中间语言(IL)代码中完全相同。

唯一的区别(在我上面的代码示例中)是在操作完成后的状态。在上面的case1中,创建了两个MyClass个实例,一个由变量something表示,另一个由变量a表示。然后,变量a将被something中的地址覆盖,最初在something中创建的那个孤立并进行垃圾收集。

在上面的case2中,在第一行(MyClass)中只创建了MyClass something - new MyClass(); MyClass a = something;的一个实例。在同一行中,此实例的地址放在变量“. assigning to in the second line does notcreate a new instance of {MyClass`中,它只是创建一个新的引用变量,现在也指向同样的例子。

因此,两种情况之间的区别在于,在第一种情况下,创建了两个实例,其中一个是孤立的(第二个),而在第二种情况下,只创建了一个实例。在这两种情况下,最终都会有两个变量(asomething)都指向同一个实例。