当我们在计算中使用 out 或 ref 时,有多个赋值并从中读取,它有什么缺点?会影响性能吗?
static bool TrySomeFunction(int x, int y, out int result)
{
result = 8;
for (int i = 0; i < x; i++)
{
result += result + x;
if (result == y)
return false;
}
return true;
}
或者我们应该更好地使用附加变量:
static bool TrySomeFunction(int x, int y, out int result)
{
int temp = 8;
for (int i = 0; i < x; i++)
{
temp += temp + x;
if (temp == y)
{
result = 0;
return false;
}
}
result = temp;
return true;
}
更新:将函数名称从 SomeFunction 更改为更明确的用途。
最佳答案
事实证明,我们做的计算越多,两者的性能差异就越大。
我相信这是意料之中的,因为在这里我们看到了额外的间接级别。 ldind和 stind用于获取/设置 out
参数(间接)和 ldoc 值的操作与 stloc用于获取/设置局部变量的值。
我认为编译器在这里无法进行任何优化(至少将 UseOutExtensively
转换为 DontUseOutExtensively
),因为如果其他线程可能会改变方法的行为在函数执行的同时写入 out
参数的位置。
测试
让我稍微简化一下您的功能,以便我们只专注于我们感兴趣的内容:
void UseOutExtensively(out int result)
{
result = 0;
for (int i = 0; i < 100; i++)
{
int temp = result;
result = temp;
}
}
void DontUseOutExtensively(out int result)
{
int temp = 8;
for (int i = 0; i < 100; i++)
{
int anotherTemp = temp;
temp = anotherTemp;
}
result = temp;
}
所以函数没有做任何有用的事情,它们只是在变量之间交换相同的值。因此我们没有复杂的添加和条件,只获取/设置一个 out
变量和获取/设置一个局部变量。
所以测试程序如下:
int Iterations = 10000000; // we'll try 10^7, 10^8 && 10^9
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
UseOutExtensively(out int result);
Console.WriteLine("Using out extensively: {0}",
sw.ElapsedMilliseconds);
sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
DontUseOutExtensively(out int result);
Console.WriteLine("Don't use out extensively: {0}",
sw.ElapsedMilliseconds);
结果:
迭代 | UseOutExtensively | DontUseOutExtensively |
---|---|---|
10^7 | 918 | 330 |
10^8 | 8850 | 3331 |
10^9 | 92009 | 34823 |
我们看到我们执行的操作越多,性能差异就越明显。
关于c# - out 和 ref 可以用作临时变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71356352/