我有一个声明
int A = 10,B=6,C=5;
我想编写一个打印函数,以便将int变量传递给它 它打印出变量名和值。
例如,如果我打印(A) 它必须返回“A:10”,然后打印(B)然后它必须返回“B:6”
简而言之,我想知道如何访问变量的名称并将其打印到c#中的字符串。我必须使用反射吗?
阅读答案后
大家好,感谢您提供的建议。我会尝试一下,但我想知道它是否在.NET 2.0中完全可能?没有类似于
#define prt(x) std::cout << #x " = '" << x << "'" << std::endl;
C / C ++中的宏?
答案 0 :(得分:25)
唯一明智的做法是使用Expression
API;但这进一步改变了代码...
static void Main() {
int A = 10, B = 6, C = 5;
Print(() => A);
}
static void Print<T>(Expression<Func<T>> expression) {
Console.WriteLine("{0}={1}",
((MemberExpression)expression.Body).Member.Name,
expression.Compile()());
}
注意:如果这是出于调试目的,请确保将[Conditional("DEBUG")]
添加到方法中,因为以这种方式使用变量会以微妙的方式更改代码的性质。
答案 1 :(得分:7)
您可以使用lambda表达式:
static void Main( string[] args ) {
int A = 50, B = 30, C = 17;
Print( () => A );
Print( () => B );
Print( () => C );
}
static void Print<T>( System.Linq.Expressions.Expression<Func<T>> input ) {
System.Linq.Expressions.LambdaExpression lambda = (System.Linq.Expressions.LambdaExpression)input;
System.Linq.Expressions.MemberExpression member = (System.Linq.Expressions.MemberExpression)lambda.Body;
var result = input.Compile()();
Console.WriteLine( "{0}: {1}", member.Member.Name, result );
}
答案 2 :(得分:5)
如果没有来自呼叫网站的一些“帮助”,这是不可能的;甚至反射都不知道局部变量的名称。
答案 3 :(得分:2)
这不可能与反射有关(参见Brian和Joel)。通常,这是不可能的,因为您无法保证将命名值传递给您的打印功能。例如,我可以轻松地执行以下操作
print(42);
print(A + 42);
这些表达式实际上都没有名称。你期望在这里打印什么?
答案 4 :(得分:2)
另一种解决方案(来自closed post):
受Jon Skeet的post启发,关于Null Reference异常处理并突然被提醒有关投影,有一种方法可以做到这一点。
这是完整的工作代码:
public static class ObjectExtensions {
public static string GetVariableName<T>(this T obj) {
System.Reflection.PropertyInfo[] objGetTypeGetProperties = obj.GetType().GetProperties();
if(objGetTypeGetProperties.Length == 1)
return objGetTypeGetProperties[0].Name;
else
throw new ArgumentException("object must contain one property");
}
}
class Program {
static void Main(string[] args) {
string strName = "sdsd";
Console.WriteLine(new {strName}.GetVariableName());
int intName = 2343;
Console.WriteLine(new { intName }.GetVariableName());
}
}
答案 5 :(得分:0)
将来我们只使用nameof运算符。
答案 6 :(得分:0)
如果您需要支持比 int
更多的类型,请使用 Expression
API 但避免使用泛型并优雅地处理不同的表达式:
private static string ToDebugOutput(params Expression<Func<object>>[] variables)
{
var sb = new StringBuilder();
foreach (var input in variables)
{
string name;
if (input.Body is UnaryExpression unary && unary.Operand is MemberExpression operand)
{
name = operand.Member.Name;
}
else if (input.Body is MemberExpression member)
{
name = member.Member.Name;
}
else
{
throw new NotSupportedException($"typeof lambda: {input.Body.GetType()}");
}
var result = input.Compile()();
sb.Append($"{name}={result}, ");
}
return sb.ToString();
}
用法:
string s = "123";
double d = 1.23;
int i2 = 123;
var out2 = ToDebugOutput(() => s, () => d, () => i2);
// out2 = "s=123, d=1.23, i2=123, "