【问题标题】:print name of the variable in c#在c#中打印变量的名称
【发布时间】:2009-04-08 12:49:02
【问题描述】:

我有一个声明

int A = 10,B=6,C=5;

我想编写一个打印函数,以便将 int 变量传递给它并 它会打印出我的变量名和值。

例如,如果我调用 print(A) 它必须返回“A: 10”,然后打印 (B) 然后它必须返回“B:6”

简而言之,我想知道如何访问变量的名称并将其打印到 c# 中的字符串。我必须使用反射吗?

阅读答案后

大家好,感谢您提供的建议。我将尝试一下,但是我想知道在 .NET 2.0 中是否有可能?没有类似的

#define prt(x) std::cout << #x " = '" << x << "'" << std::endl;

C/C++中有哪些宏?

【问题讨论】:

    标签: c# variables printing


    【解决方案1】:

    唯一明智的做法是使用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")] 添加到方法中,因为以这种方式使用变量会以微妙的方式改变代码的性质。

    【讨论】:

    • 哇。这太棒了。干得好。
    • 嗨,马克,没有什么类似于 #define prt(x) std::cout
    【解决方案2】:

    您可以使用 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 );
    }
    

    【讨论】:

      【解决方案3】:

      如果没有来自呼叫站点的“帮助”,这是不可能的;甚至反射也不知道局部变量的名称。

      【讨论】:

      • 在 C# 3.0 和 lambda 表达式中是可能的。
      • @TcKs:严格来说,它需要 .NET 3.5 以及 C# 3.0
      • 问题是“print(A)”——这是不可能的。
      【解决方案4】:

      这不可能与反射有关(请参阅 Brian 和 Joel)。通常这是不可能的,因为您不能保证将命名值传递给您的打印函数。例如,我可以轻松地执行以下操作

      print(42);
      print(A + 42);
      

      这些表达式实际上都没有名称。您希望在这里打印什么?

      【讨论】:

      • 我认为,假设将变量名传递给函数,因为用户自己将使用该程序。虽然你的思路是对的。这只是我的 POV。
      【解决方案5】:

      另一种解决方案(来自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());
          }
      }
      

      【讨论】:

      • 这使得这个问题完全可行。只需添加一个名为 prt(object obj) 的方法,然后调用 new {obj}.GVN();方法。
      【解决方案6】:

      如果您需要支持比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, "
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-08
        • 1970-01-01
        相关资源
        最近更新 更多