C# 查找传递给函数的变量名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/72121/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 11:09:04  来源:igfitidea点击:

Finding the variable name passed to a function

提问by GateKiller

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:

当我将变量“WhatIsMyName”传递给示例函数时,我希望能够获取原始变量名称的字符串。也许是这样的:

Variable.OriginalName.ToString()

Is there any way to do this?

有没有办法做到这一点?

采纳答案by Gishu

**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.

如果有帮助,您可以定义一个名为 NamedParameter 的新类,其属性为 Name 和 Param。然后将此对象作为参数传递。

回答by Konrad Rudolph

What you want isn't possible directly but you can use Expressions in C# 3.0:

你想要的不是直接可能的,但你可以在 C# 3.0 中使用表达式:

public void ExampleFunction(Expression<Func<string, string>> f) {
    Console.WriteLine((f.Body as MemberExpression).Member.Name);
}

ExampleFunction(x => WhatIsMyName);

Note that this relies on unspecified behaviour and while it does work in Microsoft's current C# and VB compilers, andin Mono's C# compiler, there's no guarantee that this won't stop working in future versions.

请注意,这依赖于未指定的行为,虽然它可以在 Microsoft 当前的 C# 和 VB 编译器以及Mono 的 C# 编译器中工作,但不能保证这不会在未来版本中停止工作。

回答by Rob Walker

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.

做到这一点的唯一方法是通过反射和堆栈遍历。您必须获得一个堆栈帧,找出您从中调用的调用函数的下落,然后使用 CodeDOM 尝试找到树的正确部分以查看表达式是什么。

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

例如,如果调用是 ExampleFunction("a" + "b") 呢?

回答by rp.

No. A reference to your string variable gets passed to the funcion--there isn't any inherent metadeta about it included. Even reflection wouldn't get you out of the woods here--working backwards from a single reference type doesn't get you enough info to do what you need to do.

不。对您的字符串变量的引用被传递给函数——不包含任何关于它的固有元数据。即使是反射也不能让你摆脱困境——从单一引用类型向后工作不会为你提供足够的信息来做你需要做的事情。

Better go back to the drawing board on this one!

最好回到这一个的绘图板上!

rp

转速

回答by Adam Vigh

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.

您可以使用反射来获取对象的所有属性,然后循环遍历它,并获取(属性的)名称与传入参数匹配的属性的值。

回答by penderi

Well had a bit of look. of courseyou 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.

好有一点看。当然你不能使用任何类型信息。此外,局部变量的名称在运行时不可用,因为它们的名称未编译到程序集的元数据中。

回答by Nate Kohari

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.

不,但是每当您发现自己在做这样极其复杂的事情时,您可能需要重新考虑您的解决方案。请记住,代码应该比编写更容易阅读。

回答by kevin42

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.

System.Environment.StackTrace 将为您提供一个包含当前调用堆栈的字符串。您可以解析它以获取信息,其中包括每个调用的变量名称。

回答by GateKiller

Thanks for all the responses. I guess I'll just have to go with what I'm doing now.

感谢所有的回应。我想我只需要按照我现在正在做的事情去做。

For those who wanted to know why I asked the above question. I have the following function:

对于那些想知道我为什么问上述问题的人。我有以下功能:

string sMessages(ArrayList aMessages, String sType) {
    string sReturn = String.Empty;
    if (aMessages.Count > 0) {
        sReturn += "<p class=\"" + sType + "\">";
        for (int i = 0; i < aMessages.Count; i++) {
            sReturn += aMessages[i] + "<br />";
        }
        sReturn += "</p>";
    }
    return sReturn;
}

I send it an array of error messages and a css class which is then returned as a string for a webpage.

我向它发送了一组错误消息和一个 css 类,然后将其作为网页的字符串返回。

Every time I call this function, I have to define sType. Something like:

每次调用这个函数,都要定义sType。就像是:

output += sMessages(aErrors, "errors");

As you can see, my variables is called aErrors and my css class is called errors. I was hoping my cold could figure out what class to use based on the variable name I sent it.

如您所见,我的变量称为 aErrors,而我的 css 类称为错误。我希望我的感冒能根据我发送的变量名找出要使用的类。

Again, thanks for all the responses.

再次感谢所有的回复。

回答by Konrad Rudolph

GateKiller, what's wrong with my workaround? You could rewrite your function trivially to use it (I've taken the liberty to improve the function on the fly):

GateKiller,我的解决方法有什么问题?你可以简单地重写你的函数来使用它(我冒昧地改进了这个函数):

static string sMessages(Expression<Func<List<string>>> aMessages) {
    var messages = aMessages.Compile()();

    if (messages.Count == 0) {
        return "";
    }

    StringBuilder ret = new StringBuilder();
    string sType = ((MemberExpression)aMessages.Body).Member.Name;

    ret.AppendFormat("<p class=\"{0}\">", sType);
    foreach (string msg in messages) {
        ret.Append(msg);
        ret.Append("<br />");
    }
    ret.Append("</p>");
    return ret.ToString();
}

Call it like this:

像这样调用它:

var errors = new List<string>() { "Hi", "foo" };
var ret = sMessages(() => errors);