题
待办事项的退出在参数 C#有任何性能影响我应该知道的? (像例外)
我的意思是,它是一个好主意,有一个循环的out
参数,将运行一对夫妇的第二个百万次的方法?
我知道这是丑陋的,但我使用它的方式Int32.TryParse
同样是使用它们 - 返回bool
说,如果一些验证是成功的,具有包含一些额外的数据,如果它是成功的out
参数
解决方案
我怀疑你会发现任何显著性能损失使用out
参数。你一定要得到的信息返回给调用者以某种方式或其他 - out
只是做不同的方式。您可能会发现还有的一些的罚款,如果你使用了大量参数的方法中,因为它可能意味着重定向的每个接入一个额外的水平。不过,我不希望它是显著。为正常,写最可读的代码和测试性能是否已经试图进一步优化之前足够好的。
编辑:这样做的其余部分是一个的一边有效。这只是对于大值类型,通常应避免这确实不相干:)
我不同意康拉德的约虽然“为所有类型的> 32位的处理类似或相同出参数对计算机级别反正返回值”断言。这里有一个小的测试程序:
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
struct BigStruct
{
public Guid guid1, guid2, guid3, guid4;
public decimal dec1, dec2, dec3, dec4;
}
class Test
{
const int Iterations = 100000000;
static void Main()
{
decimal total = 0m;
// JIT first
ReturnValue();
BigStruct tmp;
OutParameter(out tmp);
Stopwatch sw = Stopwatch.StartNew();
for (int i=0; i < Iterations; i++)
{
BigStruct bs = ReturnValue();
total += bs.dec1;
}
sw.Stop();
Console.WriteLine("Using return value: {0}",
sw.ElapsedMilliseconds);
sw = Stopwatch.StartNew();
for (int i=0; i < Iterations; i++)
{
BigStruct bs;
OutParameter(out bs);
total += bs.dec1;
}
Console.WriteLine("Using out parameter: {0}",
sw.ElapsedMilliseconds);
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static BigStruct ReturnValue()
{
return new BigStruct();
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void OutParameter(out BigStruct x)
{
x = new BigStruct();
}
}
结果:
Using return value: 11316
Using out parameter: 7461
通过使用我们直接写入数据到最终目的地,而不是将其写入到小方法的堆栈帧,然后将其复制回主方法的堆栈帧的输出参数基本上
随意批评,虽然基准程序 - !我可能错过了一些东西。
其他提示
不是性能问题,而是想出了前面的东西 - 的你不能用方差在C#4.0 使用它们。
我个人倾向于使用out
参数相当数量在我的私有强>代码(即一类的内部,具有返回多个值,而无需使用单独的类型的方法) - 但我倾向于避免他们在公共API,除了bool Try{Something}(out result)
图案。
有没有性能影响。 out
是基本相同,任何旧的参数传递,从技术角度来看。虽然它可能听起来似乎可能数据的巨大amounds被复制(例如,对于大结构),这是实际上是相同的,作为返回值。
在事实上,对于所有类型的> 32位的处理类似于out
上的机水平强参数返回值>反正。
请注意,最后的陈述并不表明返回值==在.NET out
参数。乔恩的基准测试显示,这是明显的(很遗憾),情况并非如此。事实上,使其相同,命名返回值优化一>被用在C ++编译器。同样的事情也可能在JIT的未来版本中加以改善返回大型结构的性能(但是,由于大型结构在.NET中相当罕见,这可能是不必要的优化)。
然而,(并与我的非常有限的x86汇编的知识),从函数返回对象调用通常需要在调用位置分配足够的空间,在堆栈上推地址和通过复制填充它返回值到它。这是基本相同的是out
做,仅省略该值的不必要的临时副本,因为目标存储位置可被直接访问。
用于避免出参数的主要原因是代码的可读性,而不是性能。
有关的值类型也没有真正的区别反正(他们总是复制)和引用类型是基本相同的由参考传递。
十次有九次,你最好创建自己的愚蠢记录类,而不是使用out参数 - 这是简单的阅读和理解,当你回到后面的代码
缺货参数由REF通过。因此,只有一个指针传递堆栈上。
如果你的价值类型为大,有拷贝少,但你必须取消引用每个变量使用指针。
使用一个输出参数不损害性能。 Out参数基本上是一个参考参数,所以无论是主叫用户和被叫指向同一块内存。