Skip to content

Instantly share code, notes, and snippets.

@Tornhoof
Created June 22, 2017 16:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tornhoof/2bb73db914a13825ec7c0eb89d8d6b6a to your computer and use it in GitHub Desktop.
Save Tornhoof/2bb73db914a13825ec7c0eb89d8d6b6a to your computer and use it in GitHub Desktop.
Nameof vs. Expression Tree Member Names Benchmark
``` ini
BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063)
Processor=Intel Core i7-4790K CPU 4.00GHz (Haswell), ProcessorCount=8
Frequency=3906243 Hz, Resolution=256.0005 ns, Timer=TSC
[Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0
DefaultJob : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0
```
| Method | Mean | Error | StdDev | Gen 0 | Allocated |
|-------------------------- |--------------:|-----------:|----------:|-------:|----------:|
| NameOfBenchmark | 0.0002 ns | 0.0010 ns | 0.0009 ns | - | 0 B |
| ExpressionBenchmark | 1,394.7139 ns | 10.5833 ns | 9.8996 ns | 0.2117 | 888 B |
| ExpressionNameOfBenchmark | 824.3050 ns | 4.2835 ns | 4.0068 ns | 0.1335 | 560 B |
using System;
using System.Linq.Expressions;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnostics.Windows.Configs;
namespace NameofBench
{
class Program
{
static void Main(string[] args)
{
BenchmarkDotNet.Running.BenchmarkRunner.Run<ClassMemberBench>();
}
}
[InliningDiagnoser]
[MemoryDiagnoser]
public class ClassMemberBench
{
public void UseNames(string className, string memberName)
{
}
public void UseNames<T>(Expression<Func<T, object>> expression)
{
MemberExpression member = expression.Body as MemberExpression;
if (member == null)
{
// The property access might be getting converted to object to match the func
// If so, get the operand and see if that's a member expression
member = (expression.Body as UnaryExpression)?.Operand as MemberExpression;
}
if (member == null)
{
throw new ArgumentException("Action must be a member expression.");
}
// Pass the names on to the string-based UseNames method
UseNames(typeof(T).Name, member.Member.Name);
}
public void UseNames<T>(Expression<Func<T, string>> expression)
{
ConstantExpression constant = expression.Body as ConstantExpression;
if (constant == null)
{
throw new ArgumentException("Expression must be a constant expression.");
}
UseNames(typeof(T).Name, constant.Value.ToString());
}
[Benchmark]
public void NameOfBenchmark()
{
UseNames(nameof(Foo), nameof(Foo.Bar));
}
[Benchmark]
public void ExpressionBenchmark()
{
UseNames<Foo>(t => t.Bar);
}
[Benchmark]
public void ExpressionNameOfBenchmark()
{
UseNames<Foo>(t => nameof(t.Baz));
}
}
public class Foo
{
public int Bar { get; set; } // integer so it uses Func<T, object>
public void Baz()
{
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment