为什么要用“ref"在传递对象(不是结构)时

本文关键字:对象 结构 ref quot 为什么 | 更新日期: 2023-09-27 18:03:09

哪一个在内存方面更好?我一直使用片段2..代码片段1是否优于代码片段2(性能,内存)?

Snippet 1
public void GetListOfString(ref List<string> x)
{
    x = new List<string>(){"Dave","John"};
}

Snippet 2
public List<string> GetListOfString()
{
 return new List<string>(){"Dave","John"};
}

为什么要用“ref"在传递对象(不是结构)时

首先,您的第一个示例应该使用out,而不是ref:

public void GetListOfString(out List<string> x)

方法不关心传入值是什么;它只是覆盖了原来的内容。使用out确保a)调用者在传递变量之前不需要初始化变量,b)方法本身在返回之前需要初始化变量(这将确保防止错误)。


如果有任何性能差异(我怀疑您是否可以测量),我希望第一个示例,因为它必须传递对变量的引用。通过引用传递意味着必须有一个内存位置,方法可以在其中修改变量的值。返回一个值是一个高度优化的场景,该值通常甚至存储在寄存器中。如果变量不是通过引用传递的,那么编译器也可以注册调用者的变量,以获得额外的性能增益。

当然,如果数据保存在寄存器中,而不是存储在堆栈中,这也代表了(边际的,无关紧要的,完全不重要的)内存占用的减少。

但是性能和内存占用不应该是您首先关心的问题。主要的关注点是,在99.94%的代码中,唯一的关注点是什么在语义上和操作上有意义。如果该方法需要修改调用者的变量,那么根据场景的需要通过引用传递refout。如果不是,则按值传递。时期。

请注意,如果只有一个调用者的变量需要修改,并且方法不需要返回任何东西(即void),那么让调用者处理修改变量,只返回变量的新值(即在第二个例子中)被认为是一个更好的做法。

如果在代码中,由于某种原因,您无法实现某些特定的可测量的性能或内存占用目标,并且您可以证明使用按引用传递将确保您实现该目标,那么您可以使用性能作为按引用传递的动机。否则,就不要多想了。

代码片段2在可读性和可用性方面要好得多。

在性能和内存方面也可能稍好一些。

但这只是因为调用者被迫创建一个新的列表来调用代码片段1。你可以争辩说编译器会优化掉这个开销,但是不要依赖它。

如果您在代码片段1中使用out而不是ref,那么我会说它们在性能和内存方面是相同的。

我可以理解来自不同编程语言背景的人认为代码片段1会更好,但在c#中引用类型是通过引用返回的,而不是像在其他语言中那样复制。