如果在.NET中创建一个类,它将是一个引用类型。在这个例子中,我在SomeMethod中设置了MyClass的名称。现在在Main方法中,我不需要从SomeMethod返回返回值,因为传入的参数是引用类型。我希望main方法中的实例具有新的更新名称“John”,它确实如此。
为了便于阅读,我经常收回返回值,即使不需要将更新的属性重新分配给main中的原始实例。我的假设是编译器足够聪明,不能在Main方法中重新创建MyClass的新引用。真的吗?或者编译器是否实际创建了一个新引用,并在为自己分配返回值时指向更新的值?
//My class will be a reference type
public class MyClass
{
public int ID { get; set; }
public string name { get; set; }
}
public class Main
{
//Main method of application
public void Main()
{
MyClass myClass = new MyClass();
//return value back to itself
myClass = SomeMethod(myClass);
}
public MyClass SomeMethod(MyClass myClass)
{
myClass.name = "John";
return myClass;
}
}
这是IL
instance void Main1 () cil managed
{
// Method begins at RVA 0x207c
// Code size 15 (0xf)
.maxstack 2
.locals init (
[0] class Test.MyClass myClass
)
IL_0000: newobj instance void Test.MyClass::.ctor()
IL_0005: stloc.0
IL_0006: ldarg.0
IL_0007: ldloc.0
IL_0008: call instance class Test.MyClass Test.Main::SomeMethod(class Test.MyClass)
IL_000d: stloc.0
IL_000e: ret
} // end of method Main::Main1
答案 0 :(得分:2)
它不会创建新的引用。
但是回归也没有任何意义。这应该足够了:
public void SomeMethod(MyClass myClass)
{
myClass.name = "John";
}
以上是自然的,实际上比你提出的方式更复杂。
答案 1 :(得分:1)
类作为方法的引用传递,因此您正在修改返回的相同内容。
当基于引用类型的对象传递给方法时,没有 对象的副本。而是对对象的引用 作为方法参数使用并传递。通过改变 因此,该引用将反映在调用方法中。
资料来源:http://msdn.microsoft.com/en-us/library/ms173114(v=vs.80).aspx
关于可读性:您的方法应始终不言自明。在我看来,该方法的名称应该说明它的作用。
void AddClientContextToContainer(Container destination)
答案 2 :(得分:1)
在您的情况下,您正在创建对象的一个实例。实际实例是通过new
创建的。引用本质上只是一个整数(32位系统为32位,64位系统为64位)。该整数是指对象实例在内存中的位置。 “创建新引用”与创建新整数的工作量基本相同(意味着非常非常小;它是关于计算机可以执行的最小工作单元)。
与void
替代方案相反,您的代码将执行两个(冗余)引用副本。 (一旦将方法参数复制到堆栈上的返回值,然后再从该返回值返回到原始变量。)
实际的额外工作量微不足道。它存在,但它真的很小。这里的关注应该只是可读性。如果您发现代码更易于阅读和理解,那么很好。请注意,这是一种通常仅在MyClass
不可变时使用的模式,其中返回值是对新实例的引用而不是传入的实例。这可能会导致其他人阅读混淆你的代码。如果他们错误地认为对象是不可变的,那么可能会导致......糟糕的事情。
其他人建议让方法返回void,但我会说这可能只是让类变得不可变。你已经关注了一个更不可变的模式。
答案 3 :(得分:1)
要回答你的问题,是的,编译器足够聪明,不能将返回值重新分配给同一个对象。如果我们用Reflector或dotPeek打开你的代码,你的代码就是:
public void Main()
{
MyClass myClass = new MyClass();
//return value back to itself
myClass = SomeMethod(myClass);
}
只是转换为:
public void Main()
{
this.SomeMethod(new MyClass());
}
即使我们对重新分配变量执行某些操作,它仍然会被编译器删除。例如,编译器对此进行转换:
public void Main()
{
MyClass myClass = new MyClass();
//return value back to itself
myClass = SomeMethod(myClass);
Console.WriteLine(myClass.name);
}
到那个:
public void Main()
{
Console.WriteLine(this.SomeMethod(new MyClass()).name);
}
但是像Lews Therin和Robert Jeppesen所说,你不应该这样做,因为这是不好的做法,可能会导致误解