Ошибка в 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, так что я думаю, что он уже был бы обнаружен. С другой стороны, если это так, как я задумал, я не могу придумать разумного объяснения такой конструкции...
Как вы думаете? Это ошибка? Если нет, как вы объясните это поведение?
3 ответа
Некоторое прибегая к помощи, обнаруживает некоторые мысли:
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
,
Я согласен с 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);
}
Свойство Parent в 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;
}
}
Это довольно интересно. Сначала, когда я прочитал это, я был почти уверен, что это будет ошибкой, но когда я немного подумал об этом, я пришел к выводу, что, вероятно, подразумевается, что путь должен быть не каталогом, а полным или относительным путем к файл. Так
C: \ somenonexistingpath \ к \ а \ каталог \
интерпретируется как путь к файлу без имени в каталоге... \. Это глупо, но если предположить, что программисты в Microsoft ожидали полного пути к файлу, имеет смысл не рассматривать этот случай.
РЕДАКТИРОВАТЬ:
Обратите внимание, что
c: \ dir \ makefile -> c: \ dir
c: \ dir \ build.msbuild -> c: \ dir
дать родителю, как ожидалось.