Ошибка в Directory.GetParent? - PullRequest
       19

Ошибка в Directory.GetParent?

12 голосов
/ 19 октября 2010

Меня поразило очень странное поведение метода 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 ]

10 голосов
/ 19 октября 2010

При поиске в Google обнаруживается некоторые мысли :

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.

3 голосов
/ 19 октября 2010

Я согласен с 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;
    }
}
1 голос
/ 19 октября 2010

Это довольно интересно. Сначала, когда я прочитал это, я был почти уверен, что это будет ошибкой, но когда я немного подумал об этом, я пришел к выводу, что вероятно подразумевает, что путь должен быть не каталогом, а полный или относительный путь к файлу. Так

C: \ somenonexistingpath \ к \ а \ каталог \

интерпретируется как путь к файлу без имени в каталоге ... \. Это глупо, но если предположить, что программисты в Microsoft ожидали полного пути к файлу, имеет смысл не рассматривать этот случай.

РЕДАКТИРОВАТЬ:

Обратите внимание, что

c: \ dir \ makefile -> c: \ dir

c: \ dir \ build.msbuild -> c: \ dir

дать родителю как положено.

...