为什么 GetDirectoryName 对 C:\ 返回 null?

问题描述 投票:0回答:3

我刚刚发现了一个看起来很奇怪的设计选择:

System.IO.Path.GetDirectoryName(@"C:\folder\file.ext")

返回“C:较旧”

但是

System.IO.Path.GetDirectoryName(@"C:\") 

返回空。

如果第一个示例返回“文件夹”,我可以更好地理解它。

有什么想法为什么是这种情况吗?当您只想获取文件夹路径时,you会做什么?

.net
3个回答
4
投票

好吧,我知道这个问题已经很多年没有被触及了,但是没有人真正回答“为什么会这样?”的问题,所以我要长篇大论地解释一下。

仅出于解释目的,路径对于 Windows 来说是一个概念性的东西。出于实际目的,只有两种类型的路径。

  • 本地路径 - 以驱动器号开头,C:\Folder\File.ext
  • 远程路径 - 从服务器和共享开始,\Server\Share\Folder\File.ext

我故意省略相对路径,因为所有相对路径都可以转换为上述两个路径之一的完整路径。

考虑以下代码:

var examplePaths = new[]
{
    "C:\\Folder\\File.ext",
    "C:\\Folder\\",
    "C:\\Folder",
    "C:\\",
    "C:",
    "\\\\Server\\Share\\Folder\\File.ext",
    "\\\\Server\\Share\\Folder\\",
    "\\\\Server\\Share\\Folder",
    "\\\\Server\\Share\\",
    "\\\\Server\\Share",
    "\\\\Server\\",
    "\\\\Server",
    "\\\\",
};

foreach(var path in examplePaths)
{
    var result = Path.GetDirectoryName(path) ?? "NULL";
    Console.WriteLine($"'{path}'\t'{result}'");
}

如果你运行这个,我认为这是一个有趣的模式:

 C:\Folder\File.ext                C:\Folder
 C:\Folder\                        C:\Folder 
 C:\Folder                         C:\ 
 C:\                               NULL 
 C:                                NULL 
 \\Server\Share\Folder\File.ext    \\Server\Share\Folder 
 \\Server\Share\Folder\            \\Server\Share\Folder 
 \\Server\Share\Folder             \\Server\Share 
 \\Server\Share\                   \\Server\Share 
 \\Server\Share                    NULL 
 \\Server\                         NULL 
 \\Server                          NULL 
 \\                                NULL 

让我们从概念上谈谈什么是路径。首先一直向左,是路径根。 C:\ 是根。 \Server\Share 是根目录。 (查看 GetRootLength 源代码,了解它如何确定路径的哪一部分是根。)

查看上表,我们发现返回 null 的所有内容要么是根路径本身,要么是小于根的路径。

我们可以从概念上规划事物:

 C:\Folder\File.ext                Root\Directory\Filename
 C:\Folder\                        Root\Directory\ 
 C:\Folder                         Root\Directory
 C:\                               Root\ 
 C:                                Root 
 \\Server\Share\Folder\File.ext    Root\Directory\Filename
 \\Server\Share\Folder\            Root\Directory\ 
 \\Server\Share\Folder             Root\Directory
 \\Server\Share\                   Root\ 
 \\Server\Share                    Root 
 \\Server\                         Root 
 \\Server                          Root 
 \\                                Root 

我的意思是 C: 和 \Server\Share 都是根。 \Server\Share 中的 '' 字符对该根具有特殊含义。您不能天真地返回最后一个 '' 字符剩下的任何内容。

如果您查看 GetDirectoryName 源代码,您可以看到他们考虑到了这一点,要求变量 i 大于根长度。

while (i > root && path[--i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar);

因此,如果您向此函数传递像“C:”这样的路径,则路径参数本身就是一个根。

现在,也许它不是最好的函数名称,但是 GetDirectoryName 可能会被合理地认为是“获取包含此文件(或目录)的目录”,当您这样思考时,它突然就有意义了。也许 GetParentDirectory 是一个更好的名字。

获取包含C:\Folder ile.ext的目录,明显结果是C:\Folder。

获取包含C:\Folder的目录,结果为C:\包含Folder的根目录。

获取包含 C:\ 的目录,答案必须为 NULL/无,因为根目录没有父目录。


4
投票

来自函数的文档

返回值类型:
A 包含目录的字符串 路径信息,或 空引用 (Visual Basic 中无任何内容)if 路径 表示根目录

(重点是我加的)


0
投票

实际上,该函数最好命名为 GetPathName。它返回您传递的文件名目录的完整路径。

© www.soinside.com 2019 - 2024. All rights reserved.