在.NET中将返回值分配给引用类型

时间:2012-10-12 19:47:27

标签: c# .net

如果在.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

4 个答案:

答案 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所说,你不应该这样做,因为这是不好的做法,可能会导致误解