воскресенье, 2 марта 2014 г.

CompareFiles -> "return ((file1byte - file2byte) == 0)" -> WTF?

Вот уже реализована довольно типовая задача сравнения двух файлов:



        private bool FileCompare(string file1, string file2) {
            int file1byte;
            int file2byte;
            FileStream fs1 = null;
            FileStream fs2 = null;

            if(file1 == file2) {
                return true;
            }
            try {
                fs1 = new FileStream(file1, FileMode.Open);
                fs2 = new FileStream(file2, FileMode.Open);
                if(fs1.Length != fs2.Length) {
                    return false;
                }
                do {
                    file1byte = fs1.ReadByte();
                    file2byte = fs2.ReadByte();
                }
                while((file1byte == file2byte) && (file1byte != -1));
            }
            finally {
                fs1.Close();
                fs2.Close();
            }
            return ((file1byte - file2byte) == 0);
        }

Задача старая, код тоже старый, поэтому вполне допустимо иметь не оптимальное решение. Сейчас может уже и в самом фреймворке есть средства для этой задачи. Я сразу навскидку не знаю, а копать каждый такой чих и менять на "новый и современный подход" нет возможности.

Однако сам по себе код должен быть понятен. Например, "return ((file1byte - file2byte) == 0);" выглядит магическим. Ну вот не могу я представить себе алгоритм сравнения файлов с такой операцией на выходе. Очень интересно как это здесь получилось?

Для начала, в одной строке вовлечены две переменных с областью видимости "весь метод" и надо просмотреть весь метод что бы понять почему "(X - Y) == 0" означает равенство содержимого файлов. Даже непонятно почему использована именно операция "-" и последующее сравнение с "0"? Для таких задачи более привычно видеть "==" или "return isEqual;". Ну, что есть - то есть.

Беглый просмотр метода показывает что есть цикл и в мои переменные на каждой итерации присваивается новое значение. Сюжетная линия автора становится все более детективной... Что бы понять магическое "(X - Y) == 0" уже надо обдумать каждую итерацию цикла и понять условия выхода из цикла... Ну, "return false" в середине метода - это еще куда ни шло. Хотя бы понятно. Ну, "(file1byte == file2byte)" - это тоже понятно. Затем придется RTFM-ить FileStream.ReadByte, что бы понять "!= -1". Ага, "-1" означает конец файла. Значит при одинаковой длине файлов я получу на выходе из цикла "-1" в обоих переменных, если алгоритм успешно достиг конца файла и все байты оказались равны. Либо, я получу разные значения, потому что цикл прервет операция "==". Значит операция "==" вполне уместна. А лучше сразу еще один "return false" сразу же при обнаружении расхождения + "return true" в конце.

Но почему сейчас в конце вписан "return ((file1byte - file2byte) == 0);" ? Зачем из обычного "==" был сделан "(X - Y) == 0" ? Нет ответа...