Я понимаю, что это старый пост, но все ответы в конечном итоге основаны на текстовом сравнении двух имен. Попытка получить два «нормализованных» имени, которые учитывают множество возможных способов ссылки на один и тот же файловый объект, практически невозможна. Существуют такие проблемы, как: переходы, символические ссылки, общие сетевые файлы (ссылки на один и тот же файловый объект различными способами) и т. Д. Фактически, каждый отдельный ответ, за исключением Игоря Корхова, даст абсолютно неверные результаты при определенных обстоятельствах (например, соединения, символические ссылки, ссылки в каталогах и т. д.)
В вопросе конкретно просили, чтобы решение не требовало ввода-вывода, но если вы собираетесь работать с сетевыми путями, вам абсолютно необходимо будет выполнить ввод-вывод: есть случаи, когда просто невозможно определить из какого-либо локального манипулирование строкой пути, будут ли две ссылки на файл ссылаться на один и тот же физический файл. (Это легко понять следующим образом. Предположим, что на файловом сервере есть место соединения с каталогом Windows где-то в пределах общего поддерева. В этом случае на файл можно ссылаться либо напрямую, либо через соединение. Но соединение находится на файловом сервере, и поэтому для клиента просто невозможно определить, только с помощью локальной информации, что два именующих файла ссылаются на один и тот же физический файл: информация просто недоступна локально для клиента. Таким образом, абсолютно необходимо выполнить минимальный ввод-вывод - например, откройте два дескриптора объекта файла - чтобы определить, ссылаются ли ссылки на один и тот же физический файл.)
Следующее решение выполняет некоторый ввод-вывод, хотя и очень минимальный, но правильно определяет, являются ли две ссылки на файловую систему семантически идентичными, то есть ссылаются на один и тот же объект файла. (если ни одна из спецификаций файла не ссылается на действительный объект файла, все ставки отключены):
public static bool AreFileSystemObjectsEqual(string dirName1, string dirName2)
{
//Optimization: if strings are equal, don't bother with the IO
bool bRet = string.Equals(dirName1, dirName2, StringComparison.OrdinalIgnoreCase);
if (!bRet)
{
//NOTE: we cannot lift the call to GetFileHandle out of this routine, because we _must_
// have both file handles open simultaneously in order for the objectFileInfo comparison
// to be guaranteed as valid.
using (SafeFileHandle directoryHandle1 = GetFileHandle(dirName1), directoryHandle2 = GetFileHandle(dirName2))
{
BY_HANDLE_FILE_INFORMATION? objectFileInfo1 = GetFileInfo(directoryHandle1);
BY_HANDLE_FILE_INFORMATION? objectFileInfo2 = GetFileInfo(directoryHandle2);
bRet = objectFileInfo1 != null
&& objectFileInfo2 != null
&& (objectFileInfo1.Value.FileIndexHigh == objectFileInfo2.Value.FileIndexHigh)
&& (objectFileInfo1.Value.FileIndexLow == objectFileInfo2.Value.FileIndexLow)
&& (objectFileInfo1.Value.VolumeSerialNumber == objectFileInfo2.Value.VolumeSerialNumber);
}
}
return bRet;
}
Идея для этого возникла из ответа Уоррена Стивенса на аналогичный вопрос, который я разместил в SuperUser: https://superuser.com/a/881966/241981