Late At Work вчера вечером мы пытались понять, почему что-то не удается. Проверка проверки не срабатывала, когда она не была.
Мы закончили тем, что добавили инструкцию для печати к этому коду (разобрали из 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 - (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).
Вот разобранные методы для обеих версий: working, не работает. Я не могу прочитать сборку, поэтому размещаю их здесь в надежде на разъяснение.
Я надеюсь, что ответ не является чем-то очевидным, что я полностью забыл...!
Изменить: Вот IL. Я не думаю, что с ним что-то не так, потому что он декомпилирует правильный С#:
Обновление
Подтверждено как ошибка Microsoft, исправленная в следующей версии.