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:35

System.Environment.StackTrace will give you a string that includes the current call stack. You could parse that to get the information, which includes the variable names for each call.

查看更多
倾城一夜雪
3楼-- · 2018-12-31 09:36

Well Try this Utility class,

public static class Utility
{
    public static Tuple<string, TSource> GetNameAndValue<TSource>(Expression<Func<TSource>> sourceExpression)
    {
        Tuple<String, TSource> result = null;
        Type type = typeof (TSource);
        Func<MemberExpression, Tuple<String, TSource>> process = delegate(MemberExpression memberExpression)
                                                                    {
                                                                        ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression;
                                                                        var name = memberExpression.Member.Name;
                                                                        var value = ((FieldInfo)memberExpression.Member).GetValue(constantExpression.Value);
                                                                        return new Tuple<string, TSource>(name, (TSource) value);
                                                                    };

        Expression exception = sourceExpression.Body;
        if (exception is MemberExpression)
        {
            result = process((MemberExpression)sourceExpression.Body);
        }
        else if (exception is UnaryExpression)
        {
            UnaryExpression unaryExpression = (UnaryExpression)sourceExpression.Body;
            result = process((MemberExpression)unaryExpression.Operand);
        }
        else
        {
            throw new Exception("Expression type unknown.");
        }

        return result;
    }


}

And User It Like

    /*ToDo : Test Result*/
    static void Main(string[] args)
    {
        /*Test : primivit types*/
        long maxNumber = 123123;
        Tuple<string, long> longVariable = Utility.GetNameAndValue(() => maxNumber);
        string longVariableName = longVariable.Item1;
        long longVariableValue = longVariable.Item2;

        /*Test : user define types*/
        Person aPerson = new Person() { Id = "123", Name = "Roy" };
        Tuple<string, Person> personVariable = Utility.GetNameAndValue(() => aPerson);
        string personVariableName = personVariable.Item1;
        Person personVariableValue = personVariable.Item2;

        /*Test : anonymous types*/
        var ann = new { Id = "123", Name = "Roy" };
        var annVariable = Utility.GetNameAndValue(() => ann);
        string annVariableName = annVariable.Item1;
        var annVariableValue = annVariable.Item2;

        /*Test : Enum tyoes*/
        Active isActive = Active.Yes;
        Tuple<string, Active> isActiveVariable = Utility.GetNameAndValue(() => isActive);
        string isActiveVariableName = isActiveVariable.Item1;
        Active isActiveVariableValue = isActiveVariable.Item2;
    }
查看更多
冷夜・残月
4楼-- · 2018-12-31 09:37

Well had a bit of look. of course you can't use any Type information. Also, the name of a local variable is not available at runtime because their names are not compiled into the assembly's metadata.

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

Yes! It is possible. I have been looking for a solution to this for a long time and have finally come up with a hack that solves it (it's a bit nasty). I would not recommend using this as part of your program and I only think it works in debug mode. For me this doesn't matter as I only use it as a debugging tool in my console class so I can do:

int testVar = 1;
bool testBoolVar = True;
myConsole.Writeline(testVar);
myConsole.Writeline(testBoolVar);

the output to the console would be:

testVar: 1
testBoolVar: True

Here is the function I use to do that (not including the wrapping code for my console class.

    public Dictionary<string, string> nameOfAlreadyAcessed = new Dictionary<string, string>();
    public string nameOf(object obj, int level = 1)
    {
        StackFrame stackFrame = new StackTrace(true).GetFrame(level);
        string fileName = stackFrame.GetFileName();
        int lineNumber = stackFrame.GetFileLineNumber();
        string uniqueId = fileName + lineNumber;
        if (nameOfAlreadyAcessed.ContainsKey(uniqueId))
            return nameOfAlreadyAcessed[uniqueId];
        else
        {
            System.IO.StreamReader file = new System.IO.StreamReader(fileName);
            for (int i = 0; i < lineNumber - 1; i++)
                file.ReadLine();
            string varName = file.ReadLine().Split(new char[] { '(', ')' })[1];
            nameOfAlreadyAcessed.Add(uniqueId, varName);
            return varName;
        }
    }
查看更多
柔情千种
6楼-- · 2018-12-31 09:40

**No.**I don't think so.

The variable name that you use is for your convenience and readability. The compiler doesn't need it & just chucks it out if I'm not mistaken.

If it helps, you could define a new class called NamedParameter with attributes Name and Param. You then pass this object around as parameters.

查看更多
伤终究还是伤i
7楼-- · 2018-12-31 09:40
static void Main(string[] args)
{
  Console.WriteLine("Name is '{0}'", GetName(new {args}));
  Console.ReadLine();
}

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

More details are in this blog post.

查看更多
登录 后发表回答