Ошибка в 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

дайте родителям, как ожидалось.