【问题标题】:Why doesn't StringBuilder have IndexOf method?为什么 StringBuilder 没有 IndexOf 方法?
【发布时间】:2010-11-24 12:02:23
【问题描述】:

我知道我可以调用 ToString().IndexOf(...),但我不想创建额外的字符串。我知道我可以手动编写搜索例程。我只是想知道为什么框架中还没有这样的例程。

【问题讨论】:

    标签: .net stringbuilder


    【解决方案1】:

    我知道这是一个老问题,但是我编写了一个扩展方法,它在 StringBuilder 上执行 IndexOf。它在下面。我希望它能帮助任何发现这个问题的人,无论是通过 Google 搜索还是搜索 StackOverflow

    /// <summary>
    /// Returns the index of the start of the contents in a StringBuilder
    /// </summary>        
    /// <param name="value">The string to find</param>
    /// <param name="startIndex">The starting index.</param>
    /// <param name="ignoreCase">if set to <c>true</c> it will ignore case</param>
    /// <returns></returns>
    public static int IndexOf(this StringBuilder sb, string value, int startIndex, bool ignoreCase)
    {            
        int index;
        int length = value.Length;
        int maxSearchLength = (sb.Length - length) + 1;
    
        if (ignoreCase)
        {
            for (int i = startIndex; i < maxSearchLength; ++i)
            {
                if (Char.ToLower(sb[i]) == Char.ToLower(value[0]))
                {
                    index = 1;
                    while ((index < length) && (Char.ToLower(sb[i + index]) == Char.ToLower(value[index])))
                        ++index;
    
                    if (index == length)
                        return i;
                }
            }
    
            return -1;
        }
    
        for (int i = startIndex; i < maxSearchLength; ++i)
        {
            if (sb[i] == value[0])
            {
                index = 1;
                while ((index < length) && (sb[i + index] == value[index]))
                    ++index;
    
                if (index == length)
                    return i;
            }
        }
    
        return -1;
    }
    

    【讨论】:

    【解决方案2】:

    不幸的是,为 String 实现的许多方法本来可以为 StringBuilder 实现,但没有这样做。考虑使用扩展方法来添加您关心的内容。

    【讨论】:

      【解决方案3】:

      丹尼斯,很好的解决方案。谢谢。 我建议稍微优化一下:

      public static int IndexOf(
          this StringBuilder sb,
          string value,
          int startIndex,
          bool ignoreCase)
      {
          int len = value.Length;
          int max = (sb.Length - len) + 1;
          var v1 = (ignoreCase)
              ? value.ToLower() : value;
          var func1 = (ignoreCase)
              ? new Func<char, char, bool>((x, y) => char.ToLower(x) == y)
              : new Func<char, char, bool>((x, y) => x == y);
          for (int i1 = startIndex; i1 < max; ++i1)
              if (func1(sb[i1], v1[0]))
              {
                  int i2 = 1;
                  while ((i2 < len) && func1(sb[i1 + i2], v1[i2]))
                      ++i2;
                  if (i2 == len)
                      return i1;
              }
          return -1;
      }
      

      【讨论】:

        【解决方案4】:

        StringBuilder 上调用ToString() 不会创建额外的对象,令人困惑。在内部,StringBuilder 存储一个 String 对象,用于性能;调用 ToString() 只会返回该对象。

        【讨论】:

        • 这在问题的上下文中是不正确的,如果要求 stringbuilder 修改自身 Tthen 一个 new 字符串被创建,内部缓冲区的可变性不会暴露给托管代码。
        • @ShuggyCoUk:我的评论有点油嘴滑舌。我已将其删除。
        • 为了澄清前面的评论,调用 ToString 并没有太多开销。但是在调用它之后,对 StringBuilder 的下一次修改将产生复制开销。 (这是一个有效的优化,因为 ToString 通常是对 StringBuilder 所做的最后一件事。)因此,类似 String 的方法的有效实现不能使用 ToString,这排除了对原始发布者问题的简单解决方案。
        • 这个答案具有误导性,因为它表明 ToString 方法只是返回一个已经可用的字符串。事实并非如此。有一些奇怪的代码使用wstrcpy(查看了ILSpy,.NET4中的反编译代码)从这个stringbuilder创建一个新的字符串。
        • 这里是来源:referencesource.microsoft.com/#mscorlib/system/text/… 这显然不是空操作。
        猜你喜欢
        • 1970-01-01
        • 2018-02-27
        • 2016-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多