例如,假设我调用了这个方法:
return bool.TryParse(s, out _);
这种方式比直接调用更有效率吗?
return bool.TryParse(s, out var dummy);
?
return bool.TryParse(s, out _);
这种方式比直接调用更有效率吗?
return bool.TryParse(s, out var dummy);
?
不要轻易相信任何东西,使用进行性能测试。
这是我的代码:
using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace Measure
{
public static class Program
{
static void Main(string[] args) => BenchmarkRunner.Run(typeof(Program).Assembly);
}
public class Bench
{
[Params("true", "false", "invalid")] public string Input { get; set; }
[Benchmark]
public bool IsBoolWithVariable() => bool.TryParse(Input, out var result);
[Benchmark]
public bool IsBoolDiscarding() => bool.TryParse(Input, out _);
}
}
以下是结果:
| Method | Input | Mean | Error | StdDev |
|------------------- |-------- |----------:|----------:|----------:|
| IsBoolWithVariable | false | 7.483 ns | 0.0069 ns | 0.0058 ns |
| IsBoolDiscarding | false | 7.479 ns | 0.0040 ns | 0.0034 ns |
| IsBoolWithVariable | invalid | 15.802 ns | 0.0051 ns | 0.0043 ns |
| IsBoolDiscarding | invalid | 15.838 ns | 0.0043 ns | 0.0038 ns |
| IsBoolWithVariable | true | 7.055 ns | 0.0053 ns | 0.0047 ns |
| IsBoolDiscarding | true | 7.104 ns | 0.0407 ns | 0.0381 ns |
看起来没有区别。让我们看看它是否编译为相同的 IL 代码:
IsBoolDiscarding()
:
IL_0000: ldarg.0 // this
IL_0001: call instance string Measure.Bench::get_Input()
IL_0006: ldloca.s V_0
IL_0008: call bool [System.Runtime]System.Boolean::TryParse(string, bool&)
IL_000d: ret
IsBoolWithVariable()
:
IL_0000: ldarg.0 // this
IL_0001: call instance string Measure.Bench::get_Input()
IL_0006: ldloca.s result
IL_0008: call bool [System.Runtime]System.Boolean::TryParse(string, bool&)
IL_000d: ret
所以,实际上没有任何区别。
使用丢弃运算符会更有效率,因为实际变量不会被创建,也不需要在内存中为该变量分配存储位置。
唯一可能会注意到任何真正影响的时间是如果您正在执行非常大的循环操作。
支持微软文档:https://learn.microsoft.com/en-us/dotnet/csharp/discards
丢弃与未分配变量等效;它们没有值。由于只有一个丢弃变量,并且该变量甚至可能没有分配存储空间,因此丢弃可以减少内存分配。