I understand that I can call ToString().IndexOf(...), but I don\'t want to create an extra string. I understand that I can write a search routine manually. I just wonder why
Unfortunately, many of the methods implemented for String could have been implemented for StringBuilder but that was not done. Consider using extension methods to add what you care about.
Calling ToString()
on a StringBuilder
doesn't create an extra object, confusingly. Internally, StringBuilder
stores a String object, for performance; calling ToString()
simply returns that object.
I know this is an old question, however I have written a extension method that performs an IndexOf
on a StringBuilder
. It is below. I hope it helps anyone that finds this question, either from a Google search or searching 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;
}
Dennis, great solution. Thanks. I suggest to optimize it a little:
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;
}