2009-08-31 2 views
17

Я понимаю, что я могу вызвать ToString(). IndexOf (...), но я не хочу создавать дополнительную строку. Я понимаю, что я могу вручную написать процедуру поиска. Мне просто интересно, почему такая процедура еще не существует в рамках.Почему StringBuilder не имеет метода IndexOf?

ответ

5

К сожалению, многие методы, реализованные для String, могут быть реализованы для StringBuilder, но это не было сделано. Подумайте об использовании методов расширения, чтобы добавить то, что вам нужно.

1

Вызов ToString() на StringBuilder не создает дополнительный объект, смущенно. Внутренне, StringBuilder хранит объект String для производительности; вызов ToString() просто возвращает этот объект.

+0

это неверно в контексте вопроса, если строковому конструктору предлагается изменить сам себя. Создается строка * new *, изменчивость внутреннего буфера не подвергается управляемому коду. – ShuggyCoUk

+0

@ ShuggyCoUk: мой комментарий был немного ослеп. Я удалил его. –

+10

Чтобы прояснить предыдущий комментарий, из Call ToString не так много накладных расходов. Но после того, как вы его назовете, следующая модификация StringBuilder будет нести накладные расходы. (Это правильная оптимизация, потому что ToString обычно является последней вещью, сделанной для StringBuilder.) В результате этого эффективные реализации String-подобных методов не могут использовать ToString, что исключает тривиальное решение исходной проблемы плаката. –

36

Я знаю, что это старый вопрос, однако я написал метод расширения, который выполняет IndexOf на StringBuilder. Это ниже. Я надеюсь, что это поможет любому, кто находит этот вопрос, либо от 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; 
} 
+1

Говорят [Используйте метод String.ToUpperInvariant вместо метода String.ToLowerInvariant при нормализации строк для сравнения] (https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices -струны # рекомендации-для-шнуровки использования). Я думаю, это также верно для сравнения символов: [Char.ToUpper и Char.ToLower работают аналогично методам String.ToUpper и String.ToLower, описанным в предыдущем разделе] (https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings # chartoupper-and-chartolower) – Sergey

+0

Справедливый вызов; не стесняйтесь вносить изменения в вышеупомянутый пост. – Dennis

+1

Извините, я ошибся. На самом деле Microsoft оптимизировала * ToUpperInvariant() *, а не * ToUpper() *. В этом случае мы не можем предоставить * ToUpperInvariant() * по умолчанию, поскольку это может привести к неправильному сравнению на некоторых языках, таких как турецкий. Итак, в этом отношении ваш код абсолютно правильный. – Sergey

Смежные вопросы