这两个代码之间有什么区别:
MyClass a = new MyClass();
a = "something"
和
MyClass a = "something";
在第一个代码中,它创建了MyClass对象的新副本。 但是当不使用新关键字时会发生什么?它会影响初始类(MyClass)吗?
答案 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");
此代码:
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`中,它只是创建一个新的引用变量,现在也指向同样的例子。
因此,两种情况之间的区别在于,在第一种情况下,创建了两个实例,其中一个是孤立的(第二个),而在第二种情况下,只创建了一个实例。在这两种情况下,最终都会有两个变量(a
和something
)都指向同一个实例。