【问题标题】:Good way to concatenate string representations of objects?连接对象的字符串表示的好方法?
【发布时间】:2009-10-27 19:08:53
【问题描述】:

好的,

我们的代码中有很多 where 子句。我们有同样多的方法来生成一个字符串来表示 in 条件。我试图想出一个干净的方法如下:

public static string Join<T>(this IEnumerable<T> items, string separator)
{
    var strings = from item in items select item.ToString();
    return string.Join(separator, strings.ToArray());
}

可以这样使用:

var values = new []{1, 2, 3, 4, 5, 6};
values.StringJoin(",");
// result should be:
// "1,2,3,4,5,6"

所以这是一个很好的扩展方法,可以完成非常基本的工作。我知道简单的代码并不总是能快速或高效地执行,但我只是好奇这个简单的代码会错过什么。我们团队的其他成员认为:

  • 不够灵活(无法控制字符串表示)
  • 可能内存效率不高
  • 可能不会很快

任何专家可以插话吗?

问候,

埃里克。

【问题讨论】:

  • 这里的“in”条件在哪里?

标签: c# optimization extension-methods memory-management


【解决方案1】:

关于第一个问题,您可以添加另一个'formatter'参数来控制每个项目到字符串的转换:

public static string Join<T>(this IEnumerable<T> items, string separator)
{
    return items.Join(separator, i => i.ToString());
}

public static string Join<T>(this IEnumerable<T> items, string separator, Func<T, string> formatter)
{
    return String.Join(separator, items.Select(i => formatter(i)).ToArray());
}

关于后两个问题,除非您后来遇到性能问题并发现它是一个问题,否则我不会担心。然而,这不太可能成为瓶颈......

【讨论】:

  • 李,我同意你的看法。那是我与我的团队最初的争论。我们还没有显示出任何实际的性能瓶颈。至少通过这种方法,我们可以轻松地在一个地方更新实现,我们的整个应用都会从中受益。
  • +1 表示Join 首选项,因为下面的链接表明性能差异可以忽略不计,可读性/简单性是首选。
【解决方案2】:

出于某种原因,我认为String.Join 是根据StringBuilder 类实现的。但如果不是,那么对于大输入,以下可能会表现得更好,因为它不会为迭代中的每个连接重新创建 String 对象。

public static string Join<T>(this IEnumerable<T> items, string separator)
{
    // TODO: check for null arguments.
    StringBuilder builder = new StringBuilder();
    foreach(T t in items)
    {
        builder.Append(t.ToString()).Append(separator);
    }

    builder.Length -= separator.Length;
    return builder.ToString();
}

编辑:这里是an analysis,说明何时适合使用StringBuilderString.Join

【讨论】:

  • Join() 使用对字符串 char 数组的直接访问,并且速度至少一样快。
  • Steve,很有趣,你表现出我对 StringBuilder 方法的确切担忧。如果你环顾四周,你的算法有几十种变体。实际上,受 String.Join() 方法的启发(感谢 Reflector),我可能会遵循他们的模式。我希望更多的人会在这里发布他们的算法,并用一些硬数据来支持他们的偏好。但这是一个有趣的话题。
  • 我在 SO 上发现了一个问题,该问题分析了 StringBuilderString.Join 的效率——请参阅我的编辑以获取链接。
【解决方案3】:

为什么不使用 StringBuilder,然后自己遍历集合,追加。 否则,您将创建一个字符串数组(var 字符串),然后执行 Join。

【讨论】:

    【解决方案4】:

    您缺少对序列和序列项的空值检查。是的,这不是最快和最节省内存的方式。可能只是枚举序列并将项目的字符串表示形式呈现为StringBuilder。但这真的重要吗?您是否遇到性能问题?需要优化吗?

    【讨论】:

    • 鉴于它是一种扩展方法,因此检查 null 集合是没有意义的。不过,检查集合中的项目数量可能会很好。
    • 我不明白第一点 - 如果它是一个实例方法,检查它是否为 null 没有意义,但如果它是扩展方法,你必须检查序列,因为它可能被空引用调用。
    【解决方案5】:

    这也可以:

    public static string Test(IEnumerable<T> items, string separator)
    {
        var builder = new StringBuilder();
        bool appendSeperator = false;
        if(null != items)
        {
            foreach(var item in items)
            {
                if(appendSeperator)
                {
                    builder.Append(separator)
                }
    
                builder.Append(item.ToString());
    
                appendSeperator = true;
            }
       }
    
       return builder.ToString();
    }
    

    【讨论】:

      猜你喜欢
      • 2010-10-06
      • 1970-01-01
      • 2021-02-24
      • 2013-07-23
      • 1970-01-01
      • 1970-01-01
      • 2014-11-06
      • 2013-02-27
      • 2013-07-04
      相关资源
      最近更新 更多