为什么要用“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"};
}
首先,您的第一个示例应该使用out
,而不是ref
:
public void GetListOfString(out List<string> x)
方法不关心传入值是什么;它只是覆盖了原来的内容。使用out
确保a)调用者在传递变量之前不需要初始化变量,b)方法本身在返回之前需要初始化变量(这将确保防止错误)。
如果有任何性能差异(我怀疑您是否可以测量),我希望第一个示例慢,因为它必须传递对变量的引用。通过引用传递意味着必须有一个内存位置,方法可以在其中修改变量的值。返回一个值是一个高度优化的场景,该值通常甚至存储在寄存器中。如果变量不是通过引用传递的,那么编译器也可以注册调用者的变量,以获得额外的性能增益。
当然,如果数据保存在寄存器中,而不是存储在堆栈中,这也代表了(边际的,无关紧要的,完全不重要的)内存占用的减少。
但是性能和内存占用不应该是您首先关心的问题。主要的关注点是,在99.94%的代码中,唯一的关注点是什么在语义上和操作上有意义。如果该方法需要修改调用者的变量,那么根据场景的需要通过引用传递ref
或out
。如果不是,则按值传递。时期。
请注意,如果只有一个调用者的变量需要修改,并且方法不需要返回任何东西(即void
),那么让调用者处理修改变量,只返回变量的新值(即在第二个例子中)被认为是一个更好的做法。
如果在代码中,由于某种原因,您无法实现某些特定的和可测量的性能或内存占用目标,并且您可以证明使用按引用传递将确保您实现该目标,那么您可以使用性能作为按引用传递的动机。否则,就不要多想了。
代码片段2在可读性和可用性方面要好得多。
在性能和内存方面也可能稍好一些。
但这只是因为调用者被迫创建一个新的列表来调用代码片段1。你可以争辩说编译器会优化掉这个开销,但是不要依赖它。
如果您在代码片段1中使用out
而不是ref
,那么我会说它们在性能和内存方面是相同的。
我可以理解来自不同编程语言背景的人认为代码片段1会更好,但在c#中引用类型是通过引用返回的,而不是像在其他语言中那样复制。