让我用下面的例子来解释我的问题:
public string ExampleFunction(string Variable) {
return something;
}
string WhatIsMyName = "Hello World"';
string Hello = ExampleFunction(WhatIsMyName);
Run Code Online (Sandbox Code Playgroud)
当我将变量"WhatIsMyName"传递给示例函数时,我希望能够获取原始变量名称的字符串.也许是这样的:
Variable.OriginalName.ToString()
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点?
小智 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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在致电:
param.ValidateNotNullorEmpty();
Run Code Online (Sandbox Code Playgroud)
会抛出错误:"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);
Run Code Online (Sandbox Code Playgroud)
请注意,这取决于未指定的行为,虽然它在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));
Run Code Online (Sandbox Code Playgroud)
一个主要好处是它在编译时完成,
表达式的名称是常量.在所有情况下,在编译时评估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;
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
更多详细信息,请参阅此博客文章.
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();
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
3)最慢的,不要使用.
GetParameterName3(() => variable);
public static string GetParameterName3<T>(Expression<Func<T>> expr)
{
if (expr == null)
return string.Empty;
return ((MemberExpression)expr.Body).Member.Name;
}
Run Code Online (Sandbox Code Playgroud)
要获取组合参数名称和值,可以扩展这些方法.当然,如果你将参数作为另一个参数单独传递,那么它很容易获得值,但这是不优雅的.代替:
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();
}
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
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");
}
}
Run Code Online (Sandbox Code Playgroud)
是! 有可能的。很长时间以来,我一直在寻找解决方案,最后终于提出了解决该问题的办法(有点讨厌)。我不建议将此作为程序的一部分,我只认为它可以在调试模式下工作。对我而言,这无关紧要,因为我只在控制台类中将其用作调试工具,所以可以这样做:
int testVar = 1;
bool testBoolVar = True;
myConsole.Writeline(testVar);
myConsole.Writeline(testBoolVar);
Run Code Online (Sandbox Code Playgroud)
到控制台的输出将是:
testVar: 1
testBoolVar: True
Run Code Online (Sandbox Code Playgroud)
这是我用来执行此操作的函数(不包括控制台类的包装代码。
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;
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
为了创建良好的异常消息,使人们能够更好地查明错误,这将非常有用。行号有帮助,但您可能无法在产品中获得它们,当您获得它们时,如果代码中有大语句,您通常只会获得整个语句的第一行。
例如,如果您在未设置的可为 null 的情况下调用 .Value,您将收到带有失败消息的异常,但由于缺少此功能,您将看不到哪个属性为 null。如果您在一条语句中执行此操作两次,例如为某个方法设置参数,您将无法看到未设置的可空值。
创建像Verify.NotNull(myvar, nameof(myvar)) 这样的代码是迄今为止我发现的最好的解决方法,但是如果不需要添加额外的参数,那就太好了。
Gis*_*shu -11
不,我不这么认为。
您使用的变量名称是为了方便和可读。如果我没记错的话,编译器不需要它,只是将其丢弃。
如果有帮助,您可以定义一个带有NamedParameter
属性Name
和 的新类Param
。然后将此对象作为参数传递。
归档时间: |
|
查看次数: |
49899 次 |
最近记录: |