Bug in Directory.GetParent?

后端 未结 3 1327
天命终不由人
天命终不由人 2020-12-11 02:10

I was hit in the face by a very weird behavior of the System.IO.Directory.GetParent method:

string path1 = @\"C:\\foo\\bar\";
DirectoryInfo pare         


        
相关标签:
3条回答
  • 2020-12-11 02:38

    I agree with GSerg. Just to add some additional firepower, I'm going to add the following code snippets obtained with Reflector.

    The Directory.GetParent function basically just calls the Path.GetDirectoryName function:

    [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);
    }
    

    The Parent property of the DirectoryInfo basically strips off a trailing slash and then calls 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;
        }
    }
    
    0 讨论(0)
  • 2020-12-11 02:39

    This is pretty interesting. First when I read this I was pretty sure this would be a bug, but when I thought a little bit longer about it I came to the conclusion that probably the intent is that path should not be a directory but a full or relative path to a file. So

    c:\somenonexistingpath\to\a\directory\

    gets interpreted as a path to a file with no name in ...\directory. That's kind of silly, but if we assume that the programmers at Microsoft were expecting a full path to a file, it makes sense not to cover this case.

    EDIT:

    Note that

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

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

    give the parent as expected.

    0 讨论(0)
  • 2020-12-11 02:40

    Some googling reveals some thoughts:

    DirectoryInfo di = new DirectoryInfo(@"C:\parent\child");
    Console.WriteLine(di.Parent.FullName);
    

    and

    DirectoryInfo di = new DirectoryInfo(@"C:\parent\child\");
    Console.WriteLine(di.Parent.FullName);
    

    Both return "C:\parent"

    I can only assume Directory.GetParent(...) can't assume that C:\parent\child is a directory instead of a file with no file extension. DirectoryInfo can, because you're constructing the object that way.


    Personally what I think is that when there is a backslash, the string is treated as a path to the "null file" inside the directory (that is, a file with no name and extension). Apparently, those can exist (there should be a link, but for some reason I can't find anything).

    Try constructing a FileInfo object out of path2. You'll see it's properly constructed, has String.Empty as its name and extension, does not exist and has C:\foo\bar as its DirectoryName. Given that, the situation makes sense: the parent object for this "null file" is indeed C:\foo\bar.

    0 讨论(0)
提交回复
热议问题