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 such a routine doesn't already exist in the framework.
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.
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;
}
ToUpperInvariant
should be used because it correctly upper-cases the Turkish-I whereas ToLower
and ToLowerInvariant
is incorrect? –
Smoot ToUpperInvariant()
is optimized but cannot be used for Turkish. Only ToLower()
& ToUpper()
will provide the correct result. >>> dotnetfiddle.net/YNO52f <<< So, I can't agree that ToUpperInvariant should be used because it correctly upper-cases the Turkish-I. –
Finnougrian ToLower()
-> to ToUpper()
for performance reasons mentioned above (pending approval). I would have chosen ToUpperInvariant()
, but some above said it didn't work for them as expected (eg, for Turkish). –
Divisibility 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.
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;
}
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.
StringBuilder.ToString
was changed to produce a new String
object unless it can reuse a string that has already been returned, to avoid the possibility of one thread calling ToString
while another thread is mutating the StringBuilder
. While there's no spec as to what string should be returned in that case, there shouldn't be any way by which the string which is returned can be modified after the return; the only way I know to ensure that is to return a string which has never and will never be open to modification. –
Amir ToString
method simply returns an already available string. That is not the case. There is some weird code using wstrcpy
(looked at the decompiled code in ILSpy, .NET4) to create a new string from this stringbuilder. –
Armour © 2022 - 2024 — McMap. All rights reserved.