It seems that thinking about Me
all the time is problematic outside of personal relationships as well as within them. In part 1 I discussed my JavaScript and C# implementation of Me
.
A couple of exceptionally helpful people have pointed out that my approach is rather expensive in terms of run-time speed. Being curious (and desiring to be distracted), I cooked up a quick benchmark of the two approaches (mine and the one suggested by Matt Eland).
The benchmarking code is derived from a Stackoverflow solution provided by one Alex Erygin.
First the benchmarking code:
using System;
using System.Diagnostics;
namespace dotnets
{
public class Benchmark : IDisposable
{
private readonly Stopwatch timer = new Stopwatch();
private readonly string benchmarkName;
public Benchmark(string benchmarkName)
{
this.benchmarkName = benchmarkName;
timer.Start();
}
public void Dispose()
{
timer.Stop();
Console.WriteLine($"{benchmarkName} {timer.Elapsed}");
}
}
}
Then the Main
using System;
using System.Diagnostics;
namespace dotnets
{
class Program
{
private static string Me => new StackTrace().GetFrame(1).GetMethod().Name;
static void Main(string[] args)
{
using (var bench = new Benchmark("Using Me")) {
for(var i = 0; i < 1000; i++) foo1();
}
using (var bench = new Benchmark("Using nameof")) {
for(var i = 0; i < 1000; i++) foo2();
}
}
static string foo1()
{
var me = Me;
return me;
}
static string foo2()
{
var me = nameof(foo2);
return me;
}
}
}
Then a copy of a Debug run
>dotnet run
Using Me 00:00:00.0122772
Using nameof 00:00:00.0001258
and a Release run
>dotnet run -c Release
Using Me 00:00:00.0164321
Using nameof 00:00:00.0000010
nameof
being resolved at compile-time is clearly the winner. So if run-time speed is an issue for you, use nameof
.
Top comments (3)
Thanks Bruce. I learn something new everyday!
As a suggestion for a future topic: the Dispose pattern used in .NET (I'm confused on whether it takes a bool or not).
I'm intrigued by Erygin's Dispose pattern too. What he is doing is following C#'s Destructor pattern rather than its Finalizer pattern. See Implementing IDisposable and the Dispose Pattern Properly.
It would be interesting to discover whether a Finalizer would work in the same way for a
using
block as is done in theBenchmark
object.As for the Dispose taking a second parameter, that is mentioned in the Microsoft documentation Implementing a Dispose method which says
The Destructor pattern examples I've seen so far don't use this overload. However, the CodeProject article goes into a lot of detail and does discuss the second form thoroughly.
I looked at that CodeProject article as you suggested. It's very detailed and will take me some time to fully digest. The Microsoft doc seems to be a little more precise. I'm just surprised that to use Dispose correctly, you have to keep track it's usage with your own flag. Seems like old school programming. Whenever I use flags in my stuff, our coding advisor always makes a face!
Thanks again for the information. I'll be sure to use it.