Ошибка в Directory.GetParent?
Меня поразило очень странное поведение метода System.IO.Directory.GetParent
:
string path1 = @"C:\foo\bar";
DirectoryInfo parent1 = Directory.GetParent(path1);
Console.WriteLine (parent1.FullName); // Prints C:\foo, as expected
// Notice the extra backslash. It should still refer to the same location, right ?
string path2 = @"C:\foo\bar\";
DirectoryInfo parent2 = Directory.GetParent(path2);
Console.WriteLine (parent2.FullName); // Prints C:\foo\bar !!!
Я бы подумал, что это ошибка, но этот метод существует с 1.0, поэтому я предполагаю, что он был бы обнаружен к настоящему времени. С другой стороны, если он сконструирован, я не могу представить разумного объяснения для такого дизайна...
Как вы думаете? Это ошибка? Если нет, как вы объясните это поведение?
Ответы
Ответ 1
Некоторые поисковые запросы показывают некоторые мысли:
DirectoryInfo di = new DirectoryInfo(@"C:\parent\child");
Console.WriteLine(di.Parent.FullName);
и
DirectoryInfo di = new DirectoryInfo(@"C:\parent\child\");
Console.WriteLine(di.Parent.FullName);
Оба возвращают "C:\parent"
Я могу только предположить, что Directory.GetParent(...)
не может предположить, что C:\parent\child
- это каталог, а не файл без расширения файла. DirectoryInfo
может, потому что вы таким образом создаете объект.
Лично я считаю, что когда есть обратная косая черта, строка рассматривается как путь к "нулевому файлу" внутри каталога (то есть файл без имени и расширения). По-видимому, они могут существовать (должна быть ссылка, но по какой-то причине я ничего не могу найти).
Попробуйте создать объект FileInfo
из path2
. Вы увидите, что он правильно сконструирован, имеет String.Empty
как его имя и расширение, не существует и имеет C:\foo\bar
как его DirectoryName
. Учитывая это, ситуация имеет смысл: родительский объект для этого "нулевого файла" действительно C:\foo\bar
.
Ответ 2
Я согласен с GSerg. Чтобы добавить дополнительную огневую мощь, я собираюсь добавить следующие фрагменты кода, полученные с помощью Reflector.
Функция Directory.GetParent в основном просто вызывает функцию Path.GetDirectoryName:
[SecuritySafeCritical]
public static DirectoryInfo GetParent(string path)
{
if (path == null)
{
throw new ArgumentNullException("path");
}
if (path.Length == 0)
{
throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"), "path");
}
string directoryName = Path.GetDirectoryName(Path.GetFullPathInternal(path));
if (directoryName == null)
{
return null;
}
return new DirectoryInfo(directoryName);
}
Родительское свойство DirectoryInfo в основном удаляет конечную косую черту, а затем вызывает Path.GetDirectoryName:
public DirectoryInfo Parent
{
[SecuritySafeCritical]
get
{
string fullPath = base.FullPath;
if ((fullPath.Length > 3) && fullPath.EndsWith(Path.DirectorySeparatorChar))
{
fullPath = base.FullPath.Substring(0, base.FullPath.Length - 1);
}
string directoryName = Path.GetDirectoryName(fullPath);
if (directoryName == null)
{
return null;
}
DirectoryInfo info = new DirectoryInfo(directoryName, false);
new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, info.demandDir, false, false).Demand();
return info;
}
}
Ответ 3
Это довольно интересно. Сначала, когда я прочитал это, я был уверен, что это будет ошибкой, но когда я подумал немного больше об этом, я пришел к выводу, что, вероятно, целью является то, что путь не должен быть каталогом, а полным или относительным путем к файл. Так
C:\somenonexistingpath\к\а\каталог\
интерпретируется как путь к файлу без имени в каталоге... \. Это глупо, но если предположить, что программисты в Microsoft ожидали полного пути к файлу, имеет смысл не освещать этот случай.
EDIT:
Обратите внимание, что
c:\dir\makefile → c:\dir
c:\dir\build.msbuild → c:\dir
дайте родителям, как ожидалось.