【问题标题】:Using string.Join instead of foreach使用 string.Join 代替 foreach
【发布时间】:2019-09-17 08:24:51
【问题描述】:

我正在尝试重构我的代码,使其更小、更好看。我正在尝试覆盖 ToString 方法,该方法返回类名及其当前状态的所有字段。这是我的代码:

public override string ToString()
{
    var properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(x => x.Name);
    //StringBuilder result = new StringBuilder();
    //result.Append(GetType().Name);
    //result.Append("(");
    //foreach (var e in GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(x => x.Name))
    //{
    //    result.Append(e.Name);
    //    result.Append(": ");
    //    result.Append(e.GetValue(this));
    //    result.Append(";");
    //    result.Append(" ");
    //}

    //result.Remove(result.Length - 2, 2);
    //result.Append(")");
    //return result.ToString();
} 

我得到一个建议,我可以使用 string.Join 与一些 LINQ 结合使用,这样就可以完成这项工作,但我不知道该怎么做。谢谢指教!

【问题讨论】:

  • 无论如何,我认为这段代码是一种非常糟糕的覆盖ToString 的方法。看起来您正在尝试找到一种通用方法,但实际上没有。每个班级都应该以自己的方式处理。
  • 您可以像下面的答案一样将所有内容塞进一行,但这不会使您的代码更具可读性。删除 StringBuilder 也会降低效率。为什么要强调“小”和“好看”?最好的代码是快速且易读的。

标签: c# string linq join


【解决方案1】:

应该是这样的: (已编辑:缓存属性信息,而不是在每次 ToString() 调用时重新计算)

static IEnumerable<PropertyInfo> propertyInfos;
static MyClass()
{
    propertyInfos = typeof(MyClass).GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(x => x.Name);
}

public override string ToString()
{
    return $"{GetType().Name}({string.Join("; ", propertyInfos.Select(x => $"{x.Name}: {x.GetValue(this)}"))})";
}

但是,我不建议在 ToString() 实现中使用这种反射,因为它不是很有效,而且 ToString() 实现应该很快。

【讨论】:

  • 正确,除了属性值。
  • 根据 OP 的代码,您可能希望使用 "; " 而不是 ";" 作为分隔符。
  • 与其重写ToString,不如创建一个返回类型为Enumerable的函数?这可能会更好,具体取决于它的使用位置。
  • @CamiloTerevinto 大多数反射调用都在内部缓存。
  • @Metheny 可以正常工作,但是我可以以某种方式在字符串的开头附加类名并在末尾加上右括号吗?例如原始输出是“PersonName(FirstName: A; LastName: B)”,而你的代码输出是“FirstName: A; LastName: B”?
【解决方案2】:

您可以使用ObjectDumper 来完成对类属性进行字符串化的艰苦工作。

使用示例:

class Demo
{
    public int Key { get; set; }
    public string Name { get; set; }
    public override string ToString()
    {
        return ObjectDumper.Dump(this, DumpStyle.Console);
    }
}

var demo = new Demo() { Key = 1, Name = "Foo" };
Console.WriteLine(demo.ToString());

输出:

{Demo}
  Key: 1
  Name: "Foo"

如果输出不是你想要的,你可以窃取ObjectDumpersource code,然后根据你的需要进行修改。

【讨论】:

    猜你喜欢
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-08
    • 2018-07-02
    • 2013-01-12
    • 2018-01-04
    • 1970-01-01
    相关资源
    最近更新 更多