ILSpy zeigt, dass String.IsNullOrEmpty
in Bezug auf String.Length
implementiert ist. Aber warum ist dann String.IsNullOrEmpty(s)
schneller als s.Length == 0
?
Zum Beispiel ist es in diesem Benchmark 5% schneller:
var stopwatches = Enumerable.Range(0, 4).Select(_ => new Stopwatch()).ToArray();
var strings = "A,B,,C,DE,F,,G,H,,,,I,J,,K,L,MN,OP,Q,R,STU,V,W,X,Y,Z,".Split(',');
var testers = new Func[] { s => s == String.Empty, s => s.Length == 0, s => String.IsNullOrEmpty(s), s => s == "" };
int count = 0;
for (int i = 0; i < 10000; ++i) {
stopwatches[i % 4].Start();
for (int j = 0; j < 1000; ++j)
count += strings.Count(testers[i % 4]);
stopwatches[i % 4].Stop();
}
(Andere Benchmarks zeigen ähnliche Ergebnisse. Dieser hier minimierte den Effekt von überflüssigen Prozessen auf meinem Computer. Außerdem kamen die Tests, die mit leeren Zeichenfolgen verglichen wurden, auf dasselbe Ergebnis, etwa 13% langsamer als IsNullOrEmpty
.)
Zusätzlich, warum ist IsNullOrEmpty
nur auf x86 schneller, während auf x64 String.Length
etwa 9% schneller ist?
Update: Details zur Testeinrichtung: .NET 4.0 auf 64-Bit Windows 7, Intel Core i5 Prozessor, Konsolenprojekt, kompiliert mit aktivierter "Optimierung des Codes". Allerdings war auch "JIT-Optimierung beim Modulladen unterdrücken" aktiviert (siehe akzeptierte Antwort und Kommentare).
Bei vollständig aktivierter Optimierung ist Length
etwa 14% schneller als IsNullOrEmpty
mit dem Delegaten und anderem Overhead entfernt, wie in diesem Test:
var strings = "A,B,,C,DE,F,,G,H,,,,I,J,,K,L,MN,OP,Q,R,,STU,V,,W,,X,,,Y,,Z,".Split(',');
int count = 0;
for (uint i = 0; i < 100000000; ++i)
count += strings[i % 32].Length == 0 ? 1 : 0; // Längentest durch String.IsNullOrEmpty ersetzen