让我用下面的例子来解释我的问题:
public string ExampleFunction(string Variable) { return something; } string WhatIsMyName = "Hello World"'; string Hello = ExampleFunction(WhatIsMyName);
当我将变量"WhatIsMyName"传递给示例函数时,我希望能够获取原始变量名称的字符串.也许是这样的:
Variable.OriginalName.ToString()
有没有办法做到这一点?
您想要的不是直接的,但您可以在C#3.0中使用表达式:
public void ExampleFunction(Expression> f) { Console.WriteLine((f.Body as MemberExpression).Member.Name); } ExampleFunction(x => WhatIsMyName);
请注意,这取决于未指定的行为,虽然它在Microsoft的当前C#和VB编译器以及 Mono的C#编译器中都有效,但无法保证在将来的版本中不会停止工作.
我知道这是一个老问题,但在C#6.0中他们引入了应该解决这个问题的运营商名称.运算符的名称解析传递给它的变量的名称.
您案例的用法如下所示:
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));
一个主要好处是它在编译时完成,
表达式的名称是常量.在所有情况下,在编译时评估nameof(...)以生成字符串.它的参数不在运行时进行评估,并且被认为是无法访问的代码(但它不会发出"无法访问的代码"警告).
更多信息可以在这里找到
旧版本的C 3.0及以上版本
以Nawfals为基础回答
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 item) where T : class { if (item == null) return string.Empty; return typeof(T).GetProperties()[0].Name; }
static void Main(string[] args) { Console.WriteLine("Name is '{0}'", GetName(new {args})); Console.ReadLine(); } static string GetName(T item) where T : class { var properties = typeof(T).GetProperties(); Enforce.That(properties.Length == 1); return properties[0].Name; }
更多详细信息,请参阅此博客文章.
三种方式:
1)没有反思的东西:
GetParameterName1(new { variable }); public static string GetParameterName1(T item) where T : class { if (item == null) return string.Empty; return item.ToString().TrimStart('{').TrimEnd('}').Split('=')[0].Trim(); }
2)使用反射,但这比其他两个更快.
GetParameterName2(new { variable }); public static string GetParameterName2(T item) where T : class { if (item == null) return string.Empty; return typeof(T).GetProperties()[0].Name; }
3)最慢的,不要使用.
GetParameterName3(() => variable); public static string GetParameterName3(Expression > expr) { if (expr == null) return string.Empty; return ((MemberExpression)expr.Body).Member.Name; }
要获取组合参数名称和值,可以扩展这些方法.当然,如果你将参数作为另一个参数单独传递,那么它很容易获得值,但这是不优雅的.代替:
1)
public static string GetParameterInfo1(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 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(Expression > 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和2现在具有相当的速度,3再次缓慢.
是! 有可能的。很长时间以来,我一直在寻找解决方案,最后终于提出了解决该问题的办法(有点讨厌)。我不建议将此作为程序的一部分,我只认为它可以在调试模式下工作。对我而言,这无关紧要,因为我只在控制台类中将其用作调试工具,所以可以这样做:
int testVar = 1; bool testBoolVar = True; myConsole.Writeline(testVar); myConsole.Writeline(testBoolVar);
到控制台的输出将是:
testVar: 1 testBoolVar: True
这是我用来执行此操作的函数(不包括控制台类的包装代码。
public DictionarynameOfAlreadyAcessed = new Dictionary (); 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; } }