Поздно вечером на работе мы пытались понять, почему что-то не получается.Проверка проверки завершилась неудачно, когда этого не должно было быть.
Мы закончили тем, что добавили оператор печати в этот код (дизассемблированный из Reflector для проверки того, что код на самом деле был тем, что мы написали):
public static string Redacted(string name, DateTime lastModified)
{
long ticks = lastModified.Ticks;
if ((ticks != (ticks - (ticks % 10000L))) &&
(lastModified != DateTime.MaxValue))
{
Log.Debug(string.Format("Last Modified Date = '{0}'. Ticks = '{1}'. TicksCalc = '{2}'",
lastModified.ToString("dd/MM/yyyy hh:mm:ss.fff"),
ticks, ticks - (ticks % 10000L)));
Он напечатал (переформатировал):
Last Modified Date = '22/03/2011 12:16:22.000'.
Ticks = '634363497820000000'.
TicksCalc = '634363497820000000'
Но условие состоит в том, что "ticks
" (что равно тикам, напечатанным выше) не равно "(ticks - (ticks % 10000))
"(что равно TicksCalc)!634363497820000000! = 634363497820000000?!
Чтобы определить, что здесь происходит, мы добавили еще два утверждения:
long ticks = lastModified.Ticks;
/* Added following two lines: */
long num2 = ticks - (ticks % 10000L);
Log.Debug((ticks == num2).ToString());
/* */
if ((ticks != (ticks - (ticks % 10000L))) &&
(lastModified != DateTime.MaxValue))
{
Log.Debug(string.Format("Last Modified Date = '{0}'. Ticks = '{1}'. TicksCalc = '{2}'",
lastModified.ToString("dd/MM/yyyy hh:mm:ss.fff"),
ticks, ticks - (ticks % 10000L)));
Как и положено, этот выводит true
(когдатестирование с тем же значением) и не записывал вторую строку.
Чувствуя себя немного потерянным, мы снова удалили две строки, перекомпилировали и перезапустили.Исходное поведение повторилось.
Этим утром я записал видео .
В видео в первую очередь показано попадание точки останова в метод с использованием «сломанного» кода, а затем повторная сборка и повторный запуск с использованием «рабочего» кода.Обратите внимание, что даже если отладчик показывает, что условие if
оценивается как false
, тело все еще вводится.
Я видел такие вещи раньше, когда наблюдал отладчик из-заотладчик заставляет некоторые вещи оцениваться, но это происходит независимо от того, используется ли отладчик.
Более того, это происходит только в режиме Release (т. е. с включенной оптимизацией JIT).
Вотразобрали методы для обеих версий: работает , не работает .Я не могу читать ассемблер, поэтому выкладываю их сюда в надежде на выяснение.
Я надеюсь, что ответ не является чем-то очевидным, что я полностью упустил из виду ...!
Редактировать: Вот IL.Я не думаю, что с этим что-то не так, потому что он декомпилируется на правильный C #:
Обновление :
Подтверждено Microsoft как ошибка, исправленная в следующем выпуске .