136

I would like to get the name of a variable or parameter:

For example if I have:

var myInput = "input";

var nameOfVar = GETNAME(myInput); // ==> nameOfVar should be = myInput

void testName([Type?] myInput)
{
   var nameOfParam = GETNAME(myInput); // ==> nameOfParam should be = myInput
}

How can I do it in C#?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
olidev
  • 20,058
  • 51
  • 133
  • 197
  • Do you mean, get the `type` of the variable rather than the name – Neil Knight Mar 21 '12 at 09:21
  • 1
    Check out this answer, this seems to be working: [http://stackoverflow.com/questions/716399/c-sharp-how-do-you-get-a-variables-name-as-it-was-physically-typed-in-its-dec][1] [1]: http://stackoverflow.com/questions/716399/c-sharp-how-do-you-get-a-variables-name-as-it-was-physically-typed-in-its-dec – Nick Mar 21 '12 at 09:22
  • @NeilKnight I think he actually mean the name of the variable, based on his example. – Christofer Eliasson Mar 21 '12 at 09:22
  • I think that is possible in `VB`. Never tried it for `C#`. But it is horrible programming style! – juergen d Mar 21 '12 at 09:22
  • 7
    I can't post an answer because this question has been (wrongly) marked as duplicate. In C# 6.0 you will be able to use the [`nameof` operator](https://roslyn.codeplex.com/discussions/570551) for that: `var nameOfVar = nameof(myInput); // nameOfVar == "myInput"` – Paolo Moretti Oct 29 '14 at 12:09
  • @Paolo Moretti, the answer by 'Nikola Anusev' already explains that – Umar T. May 30 '16 at 16:44
  • what about nameof(myInput) ? – AZ_ May 24 '18 at 10:21

3 Answers3

248

Pre C# 6.0 solution

You can use this to get a name of any provided member:

public static class MemberInfoGetting
{
    public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
    {
        MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
        return expressionBody.Member.Name;
    }
}

To get name of a variable:

string testVariable = "value";
string nameOfTestVariable = MemberInfoGetting.GetMemberName(() => testVariable);

To get name of a parameter:

public class TestClass
{
    public void TestMethod(string param1, string param2)
    {
        string nameOfParam1 = MemberInfoGetting.GetMemberName(() => param1);
    }
}

C# 6.0 and higher solution

You can use the nameof operator for parameters, variables and properties alike:

string testVariable = "value";
string nameOfTestVariable = nameof(testVariable);
Eugene Podskal
  • 10,270
  • 5
  • 31
  • 53
Nikola Anusev
  • 6,940
  • 1
  • 30
  • 46
  • 1
    this is great for dealing with getting a variable name. how about getting Name in parameter? thanks in advance – olidev Mar 21 '12 at 09:51
  • 1
    @devn I've edited my answer with a sample code that shows how to use the same method to get a name of parameter. – Nikola Anusev Mar 21 '12 at 11:08
  • 1
    This doesn't seem to work for me... {"Unable to cast object of type 'System.Linq.Expressions.TypedConstantExpression' to type 'System.Linq.Expressions.MemberExpression'."} – weberc2 Nov 29 '12 at 19:12
  • 1
    Those two examples in my answer are working for me. Try posting some code that duplicates the error. – Nikola Anusev Nov 29 '12 at 20:10
  • 8
    This answer relies on a non-standardized behaviour of the Microsoft C# compiler, and might break under other compilers or future versions. Refer to my [question](http://stackoverflow.com/q/11063502/1149773) and [answer](http://stackoverflow.com/a/11071271/1149773) on the topic. – Douglas Oct 03 '13 at 21:55
  • @Nikola Anusev Thanks a lot , but how to get the string value from "memberExpression" variable ? – EgyEast Sep 18 '17 at 18:48
  • @EgyEast Try getting it with `var val1 =memberExpression.Compile(); val1();` – Vinod Srivastav Jul 07 '20 at 13:47
  • **C# 10.0 and later:** - Use [CallerArgumentExpressionAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callerargumentexpressionattribute?view=net-6.0) – Fabio Aug 06 '22 at 09:30
  • `nameof(testVariable)` won't work if you pass the `testVariable` as a param beforehand, it will have the param name. –  Apr 29 '23 at 10:41
10

What you are passing to GETNAME is the value of myInput, not the definition of myInput itself. The only way to do that is with a lambda expression, for example:

var nameofVar = GETNAME(() => myInput);

and indeed there are examples of that available. However! This reeks of doing something very wrong. I would propose you rethink why you need this. It is almost certainly not a good way of doing it, and forces various overheads (the capture class instance, and the expression tree). Also, it impacts the compiler: without this the compiler might actually have chosen to remove that variable completely (just using the stack without a formal local).

Community
  • 1
  • 1
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I have a list of parameters. I want to save those values in a text file. I dont want to do it like this: "abc=" + value but: GETNAME(variable) + variable. that will be faster and more elegant. – olidev Mar 21 '12 at 09:27
  • 6
    @devn no, I absolutely guarantee that it will not be faster. It will be demonstrably slower - it needs to create a capture instance, create an expression, and parse an expression. Not faster. And elegance is subjective. Frankly, I don't think you'd go far wrong with a simple `string.Format` here. And yes, I would include the variable names inside the string, i.e. `string.Format("foo={0}, bar={1}", foo, bar)`, because: in the method they are an implementation detail, but in the file they are part of the document format, which has **nothing** to do with what the locals are called. – Marc Gravell Mar 21 '12 at 09:30
6

Alternatively,

1) Without touching System.Reflection namespace,

GETNAME(new { myInput });

public static string GETNAME<T>(T myInput) where T : class
{
    if (myInput == null)
        return string.Empty;

    return myInput.ToString().TrimStart('{').TrimEnd('}').Split('=')[0].Trim();
}

2) The below one can be faster though (from my tests)

GETNAME(new { variable });
public static string GETNAME<T>(T myInput) where T : class
{
    if (myInput == null)
        return string.Empty;

    return typeof(T).GetProperties()[0].Name;
}

You can also extend this for properties of objects (may be with extension methods):

new { myClass.MyProperty1 }.GETNAME();

You can cache property values to improve performance further as property names don't change during runtime.

The Expression approach is going to be slower for my taste. To get parameter name and value together in one go see this answer of mine

Community
  • 1
  • 1
nawfal
  • 70,104
  • 56
  • 326
  • 368
  • 1
    Actually that gives the name of type of variable. – BladeMight May 21 '18 at 19:34
  • The first example is pretty bad! You could have overriden the ToString() method and boom! – cmxl Jul 14 '18 at 16:09
  • @cmxl this is only intended for anonymous types, a bespoke model developed only to get name of member (variable, fields etc). Anyway today one should always use `nameof()` operator – nawfal Jul 16 '18 at 05:05
  • I just wanted to add a hint, because the function is not limited to anonymous types. ;) `nameof()` rocks \o/ – cmxl Jul 16 '18 at 07:59
  • Unfortunately, if I have an array that consists of a bunch of variables of type int, I can't use nameof to get the name of a particular one unless I have something like a string lookup matching the index ahead of time. – MostHated Jul 08 '21 at 03:10
  • Even now i hasn't got much better -- no matter what we do, we can never get the original passed name without somewhere rewriting code, a few lines yes; but on a large project though could be thousands of extra lines. Unfortunate, this is why I dislike C#... – osirisgothra Aug 08 '23 at 17:05