为什么在传递对象(而不是结构)时使用“ref”?

时间:2015-07-16 04:41:11

标签: c# .net

哪一个在内存方面更好?我一直使用片段2 .. Snippet 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"};

}

2 个答案:

答案 0 :(得分:4)

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

public void GetListOfString(out List<string> x)

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


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

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

但无论如何,性能和内存占用不应成为您首要关注的问题。主要关注点是,关注的所有代码的99.94%是在语义和操作上有意义的。如果该方法需要修改调用者的变量,则根据场景适当地按引用refout传递。如果没有,则传递by-value。周期。

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

如果您在代码中出现问题,由于某种原因,您无法实现某些特定的可衡量的性能或内存占用目标,并且您可以证明使用传递引用将确保您实现该目标,然后您可以将性能作为传递引用的动机。否则,不要再考虑一下。

答案 1 :(得分:1)

Snippet 2在可读性和可用性方面要好得多。

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

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

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

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