For instance, let's say I call this method:
return bool.TryParse(s, out _);
Is this any more efficient than calling it this way:
return bool.TryParse(s, out var dummy);
?
For instance, let's say I call this method:
return bool.TryParse(s, out _);
Is this any more efficient than calling it this way:
return bool.TryParse(s, out var dummy);
?
Let's not trust anything and measure with BenchmarkDotNet
.
Here's my code:
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 _);
}
}
Here's the results:
| 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 |
Looks like there's no difference. Let's see if it compiles to the same 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
So, there is no difference whatsoever.
Using the discard operator would be more efficient since an actual variable isn't created along with a storage location in memory for that variable.
The only time you would have a chance to notice any real impact would be if you were doing something in a very large loop.
Supporting MS documentation: https://learn.microsoft.com/en-us/dotnet/csharp/discards
Discards are equivalent to unassigned variables; they do not have a value. Because there is only a single discard variable, and that variable may not even be allocated storage, discards can reduce memory allocations.