获取变量或参数的名称

137

我希望获得变量或参数的名称:

例如,如果我有:

var myInput = "input";

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

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

我该怎么用C#实现这个?


你的意思是获取变量的类型而不是名称吗? - Neil Knight
1
看看这个答案,它似乎有效:https://dev59.com/PHRB5IYBdhLWcg3wHkPi - Nick
@NeilKnight我认为他实际上是根据他的例子指的变量名称。 - Christofer Eliasson
我认为这在 VB 中是可能的。但我从未在 C# 中尝试过。不过,这种编程风格太糟糕了! - juergen d
7
因为这个问题被错误地标记为重复,所以我无法发布回答。在C# 6.0中,您将能够使用nameof运算符来实现:var nameOfVar = nameof(myInput); // nameOfVar == "myInput" - Paolo Moretti
显示剩余2条评论
3个回答

251

使用 C# 6.0 之前的解决方案

你可以使用以下代码获取任何提供的成员的名称:

public static class MemberInfoGetting
{
    public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
    {
        MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
        return expressionBody.Member.Name;
    }
}
获取变量名称的方法如下:
string testVariable = "value";
string nameOfTestVariable = MemberInfoGetting.GetMemberName(() => testVariable);
获取参数名称的方法:
public class TestClass
{
    public void TestMethod(string param1, string param2)
    {
        string nameOfParam1 = MemberInfoGetting.GetMemberName(() => param1);
    }
}

C# 6.0及更高版本解决方案

您可以使用nameof运算符来获取参数、变量和属性的名称:

string testVariable = "value";
string nameOfTestVariable = nameof(testVariable);

1
这对于处理获取变量名非常有用。那么如何在参数中获取名称呢?提前致谢。 - olidev
1
@devn 我已经编辑了我的答案,并提供了一个示例代码,展示如何使用相同的方法获取参数的名称。 - Nikola Anusev
1
这似乎对我不起作用... {"无法将类型为 'System.Linq.Expressions.TypedConstantExpression' 的对象强制转换为类型 'System.Linq.Expressions.MemberExpression'."} - weberc2
1
我的回答中的这两个示例对我有效。尝试发布一些复制错误的代码。 - Nikola Anusev
8
这个答案依赖于Microsoft C#编译器的非标准行为,可能在其他编译器或未来版本中出现错误。请参考我在该主题下的问题答案 - Douglas
显示剩余4条评论

10

你传递给 GETNAME 的是 myInput,而不是 myInput 本身的定义。唯一的方法是使用 lambda 表达式,例如:

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

实际上,有一些可以作为参考的例子。然而!这种方式很可能是非常错误的。我建议你重新思考为什么需要这样做。它几乎肯定不是一个好方法,并会引入各种开销(捕获类实例和表达式树)。此外,它还会影响编译器:如果没有这个,编译器实际上可能会选择完全删除该变量(只使用堆栈而没有正式本地变量)。


我有一组参数列表,想把这些值保存到文本文件中。我不想这样做:"abc=" + value,而是用 GETNAME(variable) + variable 这样会更快更优雅。 - olidev
6
@devn 不,我绝对保证它不会更快,相反它会明显变慢——需要创建一个捕获实例、创建表达式并解析表达式。速度不会更快。另外,优雅是主观的。老实说,在这里使用简单的string.Format就足够了,我建议在字符串中包含变量名,例如:string.Format("foo={0}, bar={1}", foo, bar),因为:在该方法中,它们是实现细节,但在文件中它们是文档格式的一部分,与本地变量的名称无关。 - Marc Gravell

6

或者,

1) 不触及 System.Reflection 命名空间,

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) 虽然下面这个可能会更快(根据我的测试)

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;
}

您还可以对对象的属性进行扩展(可以使用扩展方法):
new { myClass.MyProperty1 }.GETNAME();

您可以缓存属性值以进一步提高性能,因为属性名称在运行时不会更改。

对我来说,表达式方法会比较慢。要在一次操作中获取参数名称和值,请参见我的这个答案


1
实际上,这给出了变量类型的名称。 - BladeMight
第一个例子很糟糕!你本可以重写 ToString() 方法,然后就大功告成了! - cmxl
@cmxl 这仅适用于匿名类型,这是一个专门开发的定制模型,仅用于获取成员名称(变量、字段等)。无论如何,今天应该始终使用 nameof() 运算符。 - nawfal
我只是想增加一条提示,因为此函数不仅限于匿名类型。 ;) nameof() 真棒 \o/ - cmxl
不幸的是,如果我有一个由许多 int 类型变量组成的数组,除非我事先拥有类似于字符串查找匹配索引的东西,否则我无法使用 nameof 获取特定变量的名称。 - MostHated
即使现在我也没有好多了 - 无论我们做什么,都无法得到原始的传递名称,除非在某处重写代码,几行可以,但在一个大项目中可能会有成千上万行额外的代码。不幸的是,这就是为什么我不喜欢C#... - osirisgothra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接