Nehmen wir an, wir haben:
public void TestIndex1(int index)
{
if(index < 0 || index >= _size)
ThrowHelper.ThrowArgumentOutOfRangeException();
}
public void TestIndex2(int index)
{
if((uint)index >= (uint)_size)
ThrowHelper.ThrowArgumentOutOfRangeException();
}
Lassen Sie uns diese kompilieren und ILSpy betrachten:
.method public hidebysig
instance void TestIndex1 (
int32 index
) cil managed
{
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: blt.s IL_000d
IL_0004: ldarg.1
IL_0005: ldarg.0
IL_0006: ldfld int32 TempTest.TestClass::_size
IL_000b: bge.s IL_0012
IL_000d: call void TempTest.ThrowHelper::ThrowArgumentOutOfRangeException()
IL_0012: ret
}
.method public hidebysig
instance void TestIndex2 (
int32 index
) cil managed
{
IL_0000: ldarg.1
IL_0001: ldarg.0
IL_0002: ldfld int32 TempTest.TestClass::_size
IL_0007: blt.un.s IL_000e
IL_0009: call void TempTest.ThrowHelper::ThrowArgumentOutOfRangeException()
IL_000e: ret
}
Es ist leicht zu erkennen, dass der zweite weniger Code mit einem Zweig weniger enthält.
Wirklich, es gibt überhaupt keine Besetzung, es gibt die Wahl, ob blt.s
und bge.s
oder verwendet werden soll blt.s.un
, wobei letztere die übergebenen Ganzzahlen als nicht signiert behandelt, während erstere sie als signiert behandelt.
(Hinweis für diejenigen , die nicht mit CIL, da dies eine C # Frage mit einer CIL Antwort bge.s
, blt.s
und blt.s.un
sind die „kurzen“ Versionen bge
, blt
und blt.un
jeweils. blt
Pop zwei Werte aus dem Stapel und Zweigen , wenn die ersten weniger ist als die zweite , wenn Betrachten Sie sie als vorzeichenbehaftete Werte, während blt.un
zwei Werte des Stapels und der Verzweigungen angezeigt werden, wenn der erste kleiner als der zweite ist, wenn Sie sie als vorzeichenlose Werte betrachten.
Es ist absolut ein Micro-Opt, aber es gibt Zeiten, in denen es sich lohnt, Micro-Opt zu machen. Bedenken Sie außerdem, dass dies mit dem Rest des Codes im Methodenkörper den Unterschied zwischen etwas bedeuten kann, das innerhalb der Jitter-Grenzen für Inlining liegt oder nicht, und ob sie sich die Mühe machen, einen Helfer für das Auslösen von Ausnahmen außerhalb des Bereichs zu haben Wahrscheinlich wird versucht, das Inlining sicherzustellen, wenn dies überhaupt möglich ist, und die zusätzlichen 4 Bytes könnten den Unterschied ausmachen.
In der Tat ist es sehr wahrscheinlich, dass dieser Inlining-Unterschied viel größer ist als die Reduzierung eines Zweigs. Es gibt nicht viele Fälle, in denen es sich lohnt, sich die Mühe zu machen, um sicherzustellen, dass Inlining stattfindet, aber eine Kernmethode für eine Klasse von so starker Beanspruchung, wie List<T>
sie sicherlich eine davon wäre.