(EDIT: Vea la parte inferior del poste de puntos de referencia sobre diferentes micro-optimizaciones del método)
No corte - que podría crear una nueva cadena, que en realidad no se necesita. En su lugar, mirar a través de la cadena de caracteres que no son espacios en blanco (por cualquier definición que desea). Por ejemplo:
public static bool IsEmptyOrWhitespace(string text)
{
// Avoid creating iterator for trivial case
if (text.Length == 0)
{
return true;
}
foreach (char c in text)
{
// Could use Char.IsWhiteSpace(c) instead
if (c==' ' || c=='\t' || c=='\r' || c=='\n')
{
continue;
}
return false;
}
return true;
}
También puede considerar lo que quiere el método de hacer si es text
null
.
Posibles nuevas micro-optimizaciones para experimentar con:
Es foreach
más rápido o más lento que usando un bucle for
como la de abajo? Tenga en cuenta que con el bucle for
puede eliminar la prueba "if (text.Length==0)
" al principio.
for (int i = 0; i < text.Length; i++)
{
char c = text[i];
// ...
Igual que el anterior, pero izar la llamada Length
. Tenga en cuenta que esto no es bueno para matrices normales, pero poder ser útil para cuerdas. No lo he probado.
int length = text.Length;
for (int i = 0; i < length; i++)
{
char c = text[i];
En el cuerpo del bucle, ¿hay alguna diferencia (en velocidad) entre lo que tenemos y:
if (c != ' ' && c != '\t' && c != '\r' && c != '\n')
{
return false;
}
¿Un switch/case ser más rápido?
switch (c)
{
case ' ': case '\r': case '\n': case '\t':
return false;
}
Actualización sobre el comportamiento Recorte
He estado buscando en la forma Trim
puede ser tan eficiente como este. Parece que Trim
sólo creará una nueva cadena si es necesario. Si se puede volver this
o ""
lo hará:
using System;
class Test
{
static void Main()
{
CheckTrim(string.Copy(""));
CheckTrim(" ");
CheckTrim(" x ");
CheckTrim("xx");
}
static void CheckTrim(string text)
{
string trimmed = text.Trim();
Console.WriteLine ("Text: '{0}'", text);
Console.WriteLine ("Trimmed ref == text? {0}",
object.ReferenceEquals(text, trimmed));
Console.WriteLine ("Trimmed ref == \"\"? {0}",
object.ReferenceEquals("", trimmed));
Console.WriteLine();
}
}
Esto significa que es muy importante que todos los puntos de referencia en esta pregunta deben utilizar una combinación de datos:
- Cadena vacía
- espacios en blanco
- Los espacios en blanco que rodea el texto
- texto sin espacios en blanco
Por supuesto, el equilibrio del "mundo real" entre estos cuatro es imposible predecir ...
puntos de referencia me he encontrado algunos puntos de referencia de las sugerencias originales vs mía, y la mía parece ganar en todo lo que arrojo, lo que me sorprende dados los resultados en otras respuestas.Sin embargo, también comparé la diferencia entre foreach
, for
usando text.Length
, for
usando text.Length
una vez y luego invirtiendo el orden de iteración, y for
con una longitud de elevación.
Básicamente, el ciclo for
es muy ligeramente más rápido, pero al levantar la verificación de longitud es más lento que foreach
. Invertir la dirección de bucle for
es muy ligeramente más lenta que foreach
también. Tengo la firme sospecha de que el JIT está haciendo cosas interesantes aquí, en cuanto a la eliminación de duplicados grada cheques etc.
Código: (ver my benchmarking blog entry para el marco de esto está escrito en contra)
using System;
using BenchmarkHelper;
public class TrimStrings
{
static void Main()
{
Test("");
Test(" ");
Test(" x ");
Test("x");
Test(new string('x', 1000));
Test(" " + new string('x', 1000) + " ");
Test(new string(' ', 1000));
}
static void Test(string text)
{
bool expectedResult = text.Trim().Length == 0;
string title = string.Format("Length={0}, result={1}", text.Length,
expectedResult);
var results = TestSuite.Create(title, text, expectedResult)
/* .Add(x => x.Trim().Length == 0, "Trim().Length == 0")
.Add(x => x.Trim() == "", "Trim() == \"\"")
.Add(x => x.Trim().Equals(""), "Trim().Equals(\"\")")
.Add(x => x.Trim() == string.Empty, "Trim() == string.Empty")
.Add(x => x.Trim().Equals(string.Empty), "Trim().Equals(string.Empty)")
*/
.Add(OriginalIsEmptyOrWhitespace)
.Add(IsEmptyOrWhitespaceForLoop)
.Add(IsEmptyOrWhitespaceForLoopReversed)
.Add(IsEmptyOrWhitespaceForLoopHoistedLength)
.RunTests()
.ScaleByBest(ScalingMode.VaryDuration);
results.Display(ResultColumns.NameAndDuration | ResultColumns.Score,
results.FindBest());
}
public static bool OriginalIsEmptyOrWhitespace(string text)
{
if (text.Length == 0)
{
return true;
}
foreach (char c in text)
{
if (c==' ' || c=='\t' || c=='\r' || c=='\n')
{
continue;
}
return false;
}
return true;
}
public static bool IsEmptyOrWhitespaceForLoop(string text)
{
for (int i=0; i < text.Length; i++)
{
char c = text[i];
if (c==' ' || c=='\t' || c=='\r' || c=='\n')
{
continue;
}
return false;
}
return true;
}
public static bool IsEmptyOrWhitespaceForLoopReversed(string text)
{
for (int i=text.Length-1; i >= 0; i--)
{
char c = text[i];
if (c==' ' || c=='\t' || c=='\r' || c=='\n')
{
continue;
}
return false;
}
return true;
}
public static bool IsEmptyOrWhitespaceForLoopHoistedLength(string text)
{
int length = text.Length;
for (int i=0; i < length; i++)
{
char c = text[i];
if (c==' ' || c=='\t' || c=='\r' || c=='\n')
{
continue;
}
return false;
}
return true;
}
}
Resultados:
============ Length=0, result=True ============
OriginalIsEmptyOrWhitespace 30.012 1.00
IsEmptyOrWhitespaceForLoop 30.802 1.03
IsEmptyOrWhitespaceForLoopReversed 32.944 1.10
IsEmptyOrWhitespaceForLoopHoistedLength 35.113 1.17
============ Length=1, result=True ============
OriginalIsEmptyOrWhitespace 31.150 1.04
IsEmptyOrWhitespaceForLoop 30.051 1.00
IsEmptyOrWhitespaceForLoopReversed 31.602 1.05
IsEmptyOrWhitespaceForLoopHoistedLength 33.383 1.11
============ Length=3, result=False ============
OriginalIsEmptyOrWhitespace 30.221 1.00
IsEmptyOrWhitespaceForLoop 30.131 1.00
IsEmptyOrWhitespaceForLoopReversed 34.502 1.15
IsEmptyOrWhitespaceForLoopHoistedLength 35.690 1.18
============ Length=1, result=False ============
OriginalIsEmptyOrWhitespace 31.626 1.05
IsEmptyOrWhitespaceForLoop 30.005 1.00
IsEmptyOrWhitespaceForLoopReversed 32.383 1.08
IsEmptyOrWhitespaceForLoopHoistedLength 33.666 1.12
============ Length=1000, result=False ============
OriginalIsEmptyOrWhitespace 30.177 1.00
IsEmptyOrWhitespaceForLoop 33.207 1.10
IsEmptyOrWhitespaceForLoopReversed 30.867 1.02
IsEmptyOrWhitespaceForLoopHoistedLength 31.837 1.06
============ Length=1002, result=False ============
OriginalIsEmptyOrWhitespace 30.217 1.01
IsEmptyOrWhitespaceForLoop 30.026 1.00
IsEmptyOrWhitespaceForLoopReversed 34.162 1.14
IsEmptyOrWhitespaceForLoopHoistedLength 34.860 1.16
============ Length=1000, result=True ============
OriginalIsEmptyOrWhitespace 30.303 1.01
IsEmptyOrWhitespaceForLoop 30.018 1.00
IsEmptyOrWhitespaceForLoopReversed 35.475 1.18
IsEmptyOrWhitespaceForLoopHoistedLength 40.927 1.36
¿Podría comparar también mi respuesta, por favor? –
+1 para realmente probar la diferencia – pyrocumulus
¿Podría comparar mi respuesta (IsNullOrEmpty) también? Entonces tenemos todos los métodos en una situación de banco y en un sistema. – pyrocumulus