How to Get Variable Name Using Reflection

How to get variable name using reflection?

It is not possible to do this with reflection, because variables won't have a name once compiled to IL. However, you can use expression trees and promote the variable to a closure:

static string GetVariableName<T>(Expression<Func<T>> expr)
{
var body = (MemberExpression)expr.Body;

return body.Member.Name;
}

You can use this method as follows:

static void Main()
{
var someVar = 3;

Console.Write(GetVariableName(() => someVar));
}

Note that this is pretty slow, so don't use it in performance critical paths of your application. Every time this code runs, several objects are created (which causes GC pressure) and under the cover many non-inlinable methods are called and some heavy reflection is used.

For a more complete example, see here.

UPDATE

With C# 6.0, the nameof keyword is added to the language, which allows us to do the following:

static void Main()
{
var someVar = 3;

Console.Write(nameof(someVar));
}

This is obviously much more convenient and has the same cost has defining the string as constant string literal.

Java Reflection: How to get the name of a variable?

As of Java 8, some local variable name information is available through reflection. See the "Update" section below.

Complete information is often stored in class files. One compile-time optimization is to remove it, saving space (and providing some obsfuscation). However, when it is is present, each method has a local variable table attribute that lists the type and name of local variables, and the range of instructions where they are in scope.

Perhaps a byte-code engineering library like ASM would allow you to inspect this information at runtime. The only reasonable place I can think of for needing this information is in a development tool, and so byte-code engineering is likely to be useful for other purposes too.


Update: Limited support for this was added to Java 8. Parameter (a special class of local variable) names are now available via reflection. Among other purposes, this can help to replace @ParameterName annotations used by dependency injection containers.

Get variable name. javascript reflection

Since you're using .NET as an example, let's delve briefly into that. In C#, you could create a function that takes an Expression:

void BadArgument<T>(Expression<Func<T>> argExpr)
{
}

But in order to be able to extract the variable name from a call to this function, you would have to make sure the call always uses exactly the right syntax (even though there is no way to enforce this at compile time):

if(x < 0)
BadArgument(() => x);

So it can be done, but it's very fragile and pretty slow. You're basically generating instructions to create a whole expression tree based on the lambda expression () => x, just so the function you call can parse out that expression tree and try to find the name of the argument.

Can this sort of thing be done in javascript? Sure!

In javascript, closures are produced via internal functions, so the equivalent of the above lambda expression would be:

function(){return x;}

And since javascript is a scripting language, each function is the equivalent of its own definition as a string. In other words, calling .toString() on the above function will yield:

function(){return x;}

This jsfiddle shows how you can leverage this in a logging-style function. You are then free to parse the resulting function string, which will be only slightly more trouble than parsing the .NET Expression Tree would be. Furthermore, getting the actual value of x is even easier than in .NET: you just call the function!

But just because you can do it doesn't mean you should. It's nice as a gee-whiz parlor trick, but when it comes right down to it, it's not worth it:

  • It's fragile: what if some developer doesn't use it right and gives you a function that you can't parse?
  • It doesn't work with minification: imagine getting a message that variable a had an incorrect value because your minified function changed your variable names.
  • It adds overhead: even a minifier can't shorten function(){return x;} to be smaller than "x".
  • Finally, it's complicated. 'nuff said.

Getting a variable by name using reflection in Java

You get a field

field = getClass().getDeclaredField(name);

on whatever whatever type this is, presumably com.whatever.project.Hexagon. But then you try to retrieve the field on an object of type com.badlogic.gdx.graphics.Color.

System.out.println(field.get(c));

This is wrong. The javadoc states

Returns the value of the field represented by this Field, on the
specified object.

Color does not have a Color field.

What you want is probably

field.get(this)

How to get variable name? - java

You can get all field name by reflection

Class yourClass = YourClass.class
Field[] fields = yourClass.getFields();
for(Field f: fields){
f.getName();
}

or if you want mapping then go for Map

Map<String, String> propertyToValueMap

if you are trying to read method's local variable name, then it is not that simple to fetch also a signal that you are doing something wrong

Why is it not possible to get local variable names using Reflection?

You have to differentiate between the human-readable text-based form of CLI and the machine-readable compiled form of CLI.

In text CLI, local variables indeed can have names (see §II.15.4.1.3 of ECMA-335, as explained in Damien's answer).

But in the binary form, local variables don't have names. For that, look at §II.23.2.6, where the binary format for a method's local variable signature (list of all its local variables) is specified. And it doesn't contain any mention of variable names:

LocalVarSig

So, if some tool wants to know the original name of a local variable, it has to look into the debugging information contained in the PDB file. If that's not present, there is no way to find out the name.

JavaScript Reflection: obtaining a variable's name?

1. You could try parsing the script's text.

JSFiddle Example

var x = function(){}
var myUnknownNamedVar1 = myUnknownNamedVar2 = x;

var txt = (document.currentScript && document.currentScript.textContent) ||
(document.scripts && document.scripts[1]
&& document.scripts[1].textContent);
var arr = txt.match(/var\s*(.*)\s*=\s*x\b/);
arr[1] = arr[1].replace(/\s+$/,"");
var vars = arr[1].split(/\s*=\s*/);

// vars: ["myUnknownNamedVar1", "myUnknownNamedVar2"]


2. You can try comparing values

JSFiddle Example

var x = function(){}
var myUnknownNamedVar1 = myUnknownNamedVar2 = x;

var vars = [];
for (var prop in window){
if (window[prop] == x)
vars.push(prop);
}

// vars: ["x", "myUnknownNamedVar1", "myUnknownNamedVar2"]

Note: Both methods will need refining (eg recursion, better/more match patterns). The second one only looks at global variables, whereas some variables in closures may not be exposed to the global namespace. Also, there are objects of objects.



Related Topics



Leave a reply



Submit