我创建了一个轻量级类,其构造函数需要约10个参数。该类不会更改参数值,它只是通过构造函数将这些值本地存储。
有些参数是引用类型(如字符串、类),而其他参数是值类型(如int、bool、枚举)。
我的问题是,除了类之外,是否应该通过引用传递所有参数,即使用关键字ref
?
我的考虑是性能方面的。
我创建了一个轻量级类,其构造函数需要约10个参数。该类不会更改参数值,它只是通过构造函数将这些值本地存储。
有些参数是引用类型(如字符串、类),而其他参数是值类型(如int、bool、枚举)。
我的问题是,除了类之外,是否应该通过引用传递所有参数,即使用关键字ref
?
我的考虑是性能方面的。
只有当方法需要更改参数并且这些更改需要传递给调用的代码时,才使用ref
。如果您已经通过性能分析器运行过它,并确定瓶颈确实是CLR将方法参数复制到堆栈上,那么您才应该优化此操作。
请记住,CLR已经对带参数的方法进行了大量优化,因此我认为这不会是问题所在。
我发现对于较大的值类型,通过引用传递参数在高频函数调用中速度更快,略微地。如果你需要高效的函数调用并且有许多这样的调用,那么这可能是一个考虑因素。我也愿意接受其他证据。
public static void PassValue(decimal value)
{
}
public static void PassRef(ref decimal value)
{
}
decimal passMe = 0.00010209230982047828903749827394729385792342352345m;
for (int x = 0; x < 20; x++)
{
DateTime start = DateTime.UtcNow;
TimeSpan taken = new TimeSpan();
for (int i = 0; i < 50000000; i++)
{
PassValue(passMe);
}
taken = (DateTime.UtcNow - start);
Console.WriteLine("Value : " + taken.TotalMilliseconds);
start = DateTime.UtcNow;
for (int i = 0; i < 50000000; i++)
{
PassRef(ref passMe);
}
taken = (DateTime.UtcNow - start);
Console.WriteLine("Ref : " + taken.TotalMilliseconds);
}
结果:
Value : 150
Ref : 140
Value : 150
Ref : 143
Value : 151
Ref : 143
Value : 152
Ref : 144
Value : 152
Ref : 143
Value : 154
Ref : 144
Value : 152
Ref : 143
Value : 154
Ref : 143
Value : 157
Ref : 143
Value : 153
Ref : 144
Value : 154
Ref : 147
Value : 153
Ref : 144
Value : 153
Ref : 144
Value : 153
Ref : 146
Value : 152
Ref : 144
Value : 153
Ref : 143
Value : 153
Ref : 143
Value : 153
Ref : 144
Value : 153
Ref : 144
Value : 152
Ref : 143
不需要。对于引用类型,你已经传递了一个引用,除非你想改变引用指向的内容(例如分配新对象),否则没有必要通过引用来传递引用。 对于值类型,你可以通过引用传递,但是除非存在性能问题,否则我不建议这样做。特别是如果涉及到的类型很小(4个字节或更小),那么几乎没有性能增益,甚至可能会有性能损失。
ref
不会装箱该值。它传递了一个引用(指针)到持有该值的变量。 - Peter Duniho对于C#,我不确定,但对于C++/C,它取决于你传递的内容。如果你传递的是基本类型(int、float、double、char)……那么按值传递比按引用传递更快(因为函数调用针对此进行了优化)。 如果你传递的是更大的东西,比如一个大类、一个数组、一个长字符串……那么按引用传递要快得多,因为如果你正在处理一个int[100000],那么处理器将不得不分配一个100000 x 32/64(取决于架构)的块,然后复制所有的值,这需要很长时间。而通过引用只需传递一个指针。
C#抽象出了大部分内容,所以我不知道它做了什么,但我认为在效率方面适用于C++/C的内容通常也适用于C#。
ref
可以节省复制结构体的时间,你也不能将ref
作为类成员,ref
只在方法内有用。 - Kobi