接受ref类型并对其进行操作的void方法和向同一对象返回ref的方法之间有什么区别吗

本文关键字:方法 ref 对象 返回 之间 区别 什么 接受 void 操作 类型 | 更新日期: 2023-09-27 18:21:20

如果操作相同,这两个之间有很大区别吗?在示例1中,传递对对象的引用,并操纵对象。在示例2中,传递对对象的引用,操纵对象,然后。。。是否返回相同的引用?

static void Foo(SomeReferenceType t)
{
    //Do something with t
}
static SomeReferenceType Foo(SomeReferenceType t)
{
    //Do same thing with t
    return t;
}
Bar bar = new Bar();
//Does this
Foo(bar);
//Do the same thing as this
bar = Foo(bar);

接受ref类型并对其进行操作的void方法和向同一对象返回ref的方法之间有什么区别吗

后者允许在fluent类型接口中链接方法,但它可以隐藏对象被操纵的事实。操纵以这种方式传递的对象并不常见,因为当方法的消费者的对象发生变异时,他们会感到困惑。您可以克隆对象,对其进行操作,然后返回操作后的克隆。这会使初始引用中的对象保持不变。

在前者中,使用者传递一个变量并说:"亲爱的方法,请接受这个变量,并对它做任何你想做的事情,包括可能将它指向一个新的内存地址。"因此,开发人员知道传递的状态可能会被操纵。

顺便说一句,我想你应该读一下:http://msdn.microsoft.com/en-us/library/0f66670z(v=vs.71).aspx

当我采访潜在的开发人员时,我会问很多关于通过引用和值传递引用和值类型的问题。我采访过一些非常高级职位的开发人员,他们不理解这一点,但我认为这是C#开发的基础。

这对我来说也是一个可读性问题。除了已经发布的一些其他答案外,我认为返回SomeReferenceType表明传入的原始实例将保持不变,并且任何突变都将在返回的实例(应该是一个单独的对象)上执行。如果我使用这个代码,我会认为原作者建议我可以保存对原始类型的引用,并相信它不会发生突变。

如果该方法的唯一意图是对对象进行变异,则应在SomeReferenceType类中对其进行定义,以便将其修改的方法和数据封装在一起:

class SomeReferenceType()
{
  public void Foo()
  {
      // mutate instance here
  }
}
SomeReferenceType a = new SomeReferenceType();
a.Foo();

我能看到的唯一显著区别是,在返回对象的情况下,您实际上可以返回同一类的不同实例。但在您的示例中,它们在功能上是相同的

一个关键的概念差异可能是返回相同类型的不同的对象实例,也就是说,当您执行一个"操纵"一个不可变对象(如string)的方法时,每个方法都会返回一个新的、不同的string对象。

当然,如果方法是实例方法(或扩展方法),您可以将方法调用与第二种方法链接起来,这样您就可以在返回的对象实例上调用其他方法,从而实现更流畅的交互,即:

SomeReferenceType result = obj.Foo()
                              .Bar()
                              .Baz()

在这种特殊情况下,是的,它会做完全相同的事情。

为了形式起见,我会选择void函数,而不是返回对象的函数,因为如果您的函数返回对象,那么稍后维护代码的人可能会认为该函数确实创建了一个新实例,而参数中传递的对象保持不变。