让我用下面的例子来解释我的问题:
public string ExampleFunction(string Variable) {
    return something;
}
string WhatIsMyName = "Hello World"';
string Hello = ExampleFunction(WhatIsMyName);
当我将变量"WhatIsMyName"传递给示例函数时,我希望能够获取原始变量名称的字符串.也许是这样的:
Variable.OriginalName.ToString()
有没有办法做到这一点?
小智 61
我知道这篇文章确实很旧,但由于 C#10 编译器现在有一种方法,我想我应该分享一下,以便其他人知道。
您现在可以使用CallerArgumentExpressionAttribute,如图所示
// Will throw argument exception if string IsNullOrEmpty returns true
public static void ValidateNotNullorEmpty(
  this string str,
  [CallerArgumentExpression("str")]string strName = null
)
{       
  if (string.IsNullOrEmpty(str))
  {
    throw new ArgumentException($"'{strName}' cannot be null or empty.", strName);
  }
}
现在致电:
param.ValidateNotNullorEmpty();
会抛出错误:"param cannot be null or empty."
而不是“str 不能为空”
Kon*_*lph 58
您想要的不是直接的,但您可以在C#3.0中使用表达式:
public void ExampleFunction(Expression<Func<string, string>> f) {
    Console.WriteLine((f.Body as MemberExpression).Member.Name);
}
ExampleFunction(x => WhatIsMyName);
请注意,这取决于未指定的行为,虽然它在Microsoft的当前C#和VB编译器以及 Mono的C#编译器中都有效,但无法保证在将来的版本中不会停止工作.
joh*_*y 5 31
我知道这是一个老问题,但在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>(T item) where T : class
{
    if (item == null)
        return string.Empty;
    return typeof(T).GetProperties()[0].Name;
}
Rin*_*lin 19
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;
}
更多详细信息,请参阅此博客文章.
naw*_*fal 14
三种方式:
1)没有反思的东西:
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)使用反射,但这比其他两个更快.
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)最慢的,不要使用.
GetParameterName3(() => variable);
public static string GetParameterName3<T>(Expression<Func<T>> expr)
{
    if (expr == null)
        return string.Empty;
    return ((MemberExpression)expr.Body).Member.Name;
}
要获取组合参数名称和值,可以扩展这些方法.当然,如果你将参数作为另一个参数单独传递,那么它很容易获得值,但这是不优雅的.代替:
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和2现在具有相当的速度,3再次缓慢.
继续Caller*属性系列(即CallerMemberName、CallerFilePath和CallerLineNumber),CallerArgumentExpressionAttribute自 C# Next 起可用(更多信息请参见此处)。
以下示例的灵感来自 Paul Mcilreavy 的C# 8.0 中的 CallerArgumentExpression 属性:
public static void ThrowIfNullOrWhitespace(this string self, 
             [CallerArgumentExpression("self")] string paramName = default)
{
    if (self is null)
    {
        throw new ArgumentNullException(paramName);
    }
    if (string.IsNullOrWhiteSpace(self))
    {
        throw new ArgumentOutOfRangeException(paramName, self, "Value cannot be whitespace");
    }        
}
是! 有可能的。很长时间以来,我一直在寻找解决方案,最后终于提出了解决该问题的办法(有点讨厌)。我不建议将此作为程序的一部分,我只认为它可以在调试模式下工作。对我而言,这无关紧要,因为我只在控制台类中将其用作调试工具,所以可以这样做:
int testVar = 1;
bool testBoolVar = True;
myConsole.Writeline(testVar);
myConsole.Writeline(testBoolVar);
到控制台的输出将是:
testVar: 1
testBoolVar: True
这是我用来执行此操作的函数(不包括控制台类的包装代码。
    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;
        }
    }
小智 5
为了创建良好的异常消息,使人们能够更好地查明错误,这将非常有用。行号有帮助,但您可能无法在产品中获得它们,当您获得它们时,如果代码中有大语句,您通常只会获得整个语句的第一行。
例如,如果您在未设置的可为 null 的情况下调用 .Value,您将收到带有失败消息的异常,但由于缺少此功能,您将看不到哪个属性为 null。如果您在一条语句中执行此操作两次,例如为某个方法设置参数,您将无法看到未设置的可空值。
创建像Verify.NotNull(myvar, nameof(myvar)) 这样的代码是迄今为止我发现的最好的解决方法,但是如果不需要添加额外的参数,那就太好了。
Gis*_*shu -11
不,我不这么认为。
您使用的变量名称是为了方便和可读。如果我没记错的话,编译器不需要它,只是将其丢弃。
如果有帮助,您可以定义一个带有NamedParameter属性Name和 的新类Param。然后将此对象作为参数传递。
| 归档时间: | 
 | 
| 查看次数: | 49899 次 | 
| 最近记录: |