Finding the variable name passed to a function

2018-12-31 09:16发布

Let me use the following example to explain my question:

public string ExampleFunction(string Variable) {
    return something;
}

string WhatIsMyName = "Hello World"';
string Hello = ExampleFunction(WhatIsMyName);

When I pass the variable "WhatIsMyName" to the example function, I want to be able to get a string of the original variables name. Perhaps something like:

Variable.OriginalName.ToString()

Is there any way to do this?

标签: c#
16条回答
情到深处是孤独
2楼-- · 2018-12-31 09:21

No, but whenever you find yourself doing extremely complex things like this, you might want to re-think your solution. Remember that code should be easier to read than it was to write.

查看更多
墨雨无痕
3楼-- · 2018-12-31 09:23

You could use reflection to get all the properties of an object, than loop through it, and get the value of the property where the name (of the property) matches the passed in parameter.

查看更多
初与友歌
4楼-- · 2018-12-31 09:25

Do this

var myVariable = 123;
myVariable.Named(() => myVariable);
var name = myVariable.Name();
// use name how you like

or naming in code by hand

var myVariable = 123.Named("my variable");
var name = myVariable.Name();

using this class

public static class ObjectInstanceExtensions
{
    private static Dictionary<object, string> namedInstances = new Dictionary<object, string>();

    public static void Named<T>(this T instance, Expression<Func<T>> expressionContainingOnlyYourInstance)
    {
        var name = ((MemberExpression)expressionContainingOnlyYourInstance.Body).Member.Name;
        instance.Named(name);            
    }

    public static T Named<T>(this T instance, string named)
    {
        if (namedInstances.ContainsKey(instance)) namedInstances[instance] = named;
        else namedInstances.Add(instance, named);
        return instance;
    }        

    public static string Name<T>(this T instance)
    {
        if (namedInstances.ContainsKey(instance)) return namedInstances[instance];
        throw new NotImplementedException("object has not been named");
    }        
}

Code tested and most elegant I can come up with.

查看更多
呛了眼睛熬了心
5楼-- · 2018-12-31 09:27

I know this is an old question but in C# 6.0 they Introduce the nameof Operator which should solve this issue. The name of operator resolves the name of the variable passed into it.

Usage for your case would look like this:

public string ExampleFunction(string variableName) {
      //Construct your log statement using c# 6.0 string interpolation
       return $"Error occurred in {variableName}";
}

string WhatIsMyName = "Hello World"';
string Hello = ExampleFunction(nameof(WhatIsMyName));

A major benefit is that it is done at compile time,

The nameof expression is a constant. In all cases, nameof(...) is evaluated at compile-time to produce a string. Its argument is not evaluated at runtime, and is considered unreachable code (however it does not emit an "unreachable code" warning).

More information can be found here

Older Version Of C 3.0 and above
To Build on Nawfals answer

GetParameterName2(new { variable });

//Hack to assure compiler warning is generated specifying this method calling conventions
[Obsolete("Note you must use a single parametered AnonymousType When Calling this method")]
public static string GetParameterName<T>(T item) where T : class
{
    if (item == null)
        return string.Empty;

    return typeof(T).GetProperties()[0].Name;
}
查看更多
皆成旧梦
6楼-- · 2018-12-31 09:31

Three ways:

1) Something without reflection at all:

GetParameterName1(new { variable });

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

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

2) Uses reflection, but this is way faster than other two.

GetParameterName2(new { variable });

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

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

3) The slowest of all, don't use.

GetParameterName3(() => variable);

public static string GetParameterName3<T>(Expression<Func<T>> expr)
{
    if (expr == null)
        return string.Empty;

    return ((MemberExpression)expr.Body).Member.Name;
}

To get a combo parameter name and value, you can extend these methods. Of course its easy to get value if you pass the parameter separately as another argument, but that's inelegant. Instead:

1)

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

    var param = item.ToString().TrimStart('{').TrimEnd('}').Split('=');
    return "Parameter: '" + param[0].Trim() +
           "' = " + param[1].Trim();
}

2)

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

    var param = typeof(T).GetProperties()[0];
    return "Parameter: '" + param.Name +
           "' = " + param.GetValue(item, null);
}

3)

public static string GetParameterInfo3<T>(Expression<Func<T>> expr)
{
    if (expr == null)
        return string.Empty;

    var param = (MemberExpression)expr.Body;
    return "Parameter: '" + param.Member.Name +
           "' = " + ((FieldInfo)param.Member).GetValue(((ConstantExpression)param.Expression).Value);
}

1 and 2 are of comparable speed now, 3 is again sluggish.

查看更多
孤独总比滥情好
7楼-- · 2018-12-31 09:33

The short answer is no ... unless you are really really motivated.

The only way to do this would be via reflection and stack walking. You would have to get a stack frame, work out whereabouts in the calling function you where invoked from and then using the CodeDOM try to find the right part of the tree to see what the expression was.

For example, what if the invocation was ExampleFunction("a" + "b")?

查看更多
登录 后发表回答