Software Design Blog

Journey of Rinat Abdullin

How to Find Out Variable or Parameter Name in C#?

Sometimes it might be useful to capture the name of the variable or parameter within the code to simplify error reporting or debugging.

I keep on encountering posts and comments saying that this is not possible in C#.

Well, it is not so. And there are multiple ways to do that.

Caveat. This was written in December 2008. A lot of things have changed in .NET Microsoft since then (so this code might not work as expected). I personally no longer use need this approach due to changes is development style. However, if you need something similar, you might be interested in Microsoft Code Contracts.

Anonymous class approach

Given the C# code:

static void Main(string[] args)
{
  Console.WriteLine("Name is '{0}'", GetName(new {args}));
  Console.ReadLine();
}

The output would be:

Name is 'args'

Here’s the C# code that does this:

static string GetName<T>(T item) where T : class
{
  var properties = typeof(T).GetProperties();
  Enforce.That(properties.Length == 1);
  return properties[0].Name;
}

In the method above we use anonymous type declaration to capture name of the variable (thanks to the C# compiler features) and then use reflection to get the property name.

Performance is rather reasonable - 1000000 operations complete in 0,2 seconds. Still there is a trick to make code work even faster. It is called generic type caching:

static class Cache<T>
{
  public static readonly string Name;

  static Cache()
  {
    var properties = typeof(T).GetProperties();
    Enforce.That(properties.Length == 1);
    Name = properties[0].Name;
  }
}

static string GetName<T>(T item) where T : class
{
  return Cache<T>.Name;
}

As you can see, evaluation and reflection happen only once - when the we ask for the variable name for the first time. Every other call reuses the cached value.

This technique leverages specifics of static readonly members and could be applied to other scenarios, as well.

Expression approach

As it turns out, there is another, more simple approach to find out .NET variable name, that leverages the power of Linq Expressions:

static void Main(string[] args)
{
  var domain = "matrix";
  Check(() => domain);
  Console.ReadLine();
}

static void Check<T>(Expression<Func<T>> expr)
{
  var body = ((MemberExpression)expr.Body);
  Console.WriteLine("Name is: {0}", body.Member.Name);
}

By the way, this expression-based technique is called strongly-typed reflection, and it is a really handy tool in some situations.

It is quite flexible, too. Given the expression, we can get the name and the value of the variable. So you can do this as well:

static void Check<T>(Expression<Func<T>> expr)
{
  var body = ((MemberExpression)expr.Body);
  Console.WriteLine("Name is: {0}", body.Member.Name);
  Console.WriteLine("Value is: {0}", ((FieldInfo)body.Member)
    .GetValue(((ConstantExpression)body.Expression).Value));
}

The output will be:

Name is: 'domain'
Value is: 'matrix'

Note, that performance of this code (compared to the first approach) is a bit slower. With 1000000 operations it takes 3 seconds to get the name and 6 seconds to get the value. This might be or might not be an issue in your specific scenario.

I’m considering the second approach (just pulling the names) as the replacement for the name literals in the current declaration syntax of validation rules in the Shared Libraries:

Enforce.Argument(username, () => username, 
  StringIs.ValidEmail, StringIs.Limited(3,64));

Combining name and value in one expression is also really tempting, but I’d wait a bit to see if there is a way to statically cache compiled expressions.

Update: System.Reflection.Express from the Lokad Shared Libraries encapsulates methods for this kind of reflection.

IL Parsing

This approach is a bit more complex, but it does not have the performance problems of retrieving the parameter name.

We just need to replace our Check{K} method with this code snippet:

static void Check<T>(Func<T> expr)
{
  // get IL code behind the delegate
  var il = expr.Method.GetMethodBody().GetILAsByteArray();
  // bytes 2-6 represent the field handle
  var fieldHandle = BitConverter.ToInt32(il, 2);
  // resolve the handle
  var field = expr.Target.GetType()
    .Module.ResolveField(fieldHandle);

  Console.WriteLine("Name is: {0}", field.Name);
  Console.WriteLine("Value is: {0}", expr());
}

Note that instead of dealing with the Linq Expressions (and the overhead of creating them), we leverage the delegates directly. This allows to drop the overhead of retrieving the original value by 300 times, compared to the expressions, making it negligible. Performance of the name retrieval stays the same (3-4 seconds per 1000000 operations).

There are more details on this approach in the How to Get Parameter Name and Argument Value From C# Lambda via IL?

Update: System.Reflection.Reflect from the Lokad Shared Libraries has some methods for this kind of reflection.

You can subscribe to the RSS feed of this blog, if you are interested in more updates on this topic.