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

Els*_*nov 0 .net c#

这两个代码有什么区别:

MyClass a = new MyClass();
a = "something"
Run Code Online (Sandbox Code Playgroud)

MyClass a = "something";
Run Code Online (Sandbox Code Playgroud)

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

ang*_*son 8

好吧,第二种形式是非法的,除非定义了转换运算符.

要实现此转换运算符,您必须使用new MyClass构造新实例.

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

转换运算符示例:

public class MyClass
{
    public static implicit operator MyClass(string s)
    {
        return new MyClass();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

a = "something";
Run Code Online (Sandbox Code Playgroud)

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

转换运算符定义了一个名为op_Implicit(在本例中)的静态方法,该方法将被调用,因此您的代码实际上看起来像这样:

MyClass a = new MyClass();
a = MyClass.op_Implicit("something");
Run Code Online (Sandbox Code Playgroud)

或这个:

MyClass a = MyClass.op_Implicit("something");
Run Code Online (Sandbox Code Playgroud)

如果可以读取IL,可以使用LINQPad进行验证.

这段代码:

void Main()
{
    MyClass a = "something";
    a = "xyz";
}
Run Code Online (Sandbox Code Playgroud)

转换为此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  
Run Code Online (Sandbox Code Playgroud)

注意这两个电话op_Implicit.

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

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

MyClass a = "something";             // error
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,错误消息都是:

CS0029
无法将类型'string'隐式转换为'MyClass'