Я никогда не знал компилятора C#, чтобы испускать дополнительные арифметические инструкции при генерации кода для Array.Length
. В IL, Array.Length
выглядит примерно так:
ldloc.1 // Assuming an array was stored in local slot 1
ldlen
Даже в клетчатой контексте, это то, что он выглядит. Теперь в IL нет такой вещи, как проверенный контекст, как в C#. IL имеет только различные арифметические инструкции, которые проверяются (например, add.ovf
вместо add
).
Если кто-то написал такой код:
int length = checked(array.Length - 1 + 1);
код IL, который получает испускаемый выглядит примерно так:
ldloc.1
ldlen
conv.i4
ldc.i4.1
sub.ovf
ldc.i4.1
add.ovf
stloc.2
Это не удивило бы меня, если декомпилятор лечит каждый из тех *.ovf
инструкции и инструкцию conv.i4
как имеющие свой проверенный контекст. Читая инструкции и постепенно создавая C# выражение бы получить что-то вроде следующего:
ldloc.1 // array
ldlen // array.Length
conv.i4 // checked((int) array.Length)
ldc.i4.1
sub.ovf // checked(checked((int) array.Length) - 1)
ldc.i4.1
add.ovf // checked(checked(checked((int) array.Length) - 1) + 1)
stloc.2
Возможно, код был скомпилирован в проверенном контексте. Тем не менее я не знаю, что делает этот код. Операция длины массива в действии C# возвращает собственный int. Возможно, оригинальный автор пытался выяснить, подходит ли длина в int (что в значительной степени будет) –
Но как насчет этой таинственной «-1 + 1» умственной акробатики? – ajeh
Моя догадка заключается в том, что парень пытается проверить, может ли предмет вписаться в int и не во время компиляции. –