为什么Path.Combine无法正确连接以Path.DirectorySeparatorChar开头的文件名?
从Visual Studio的立即窗口中:
> Path.Combine(@"C:\x", "y") "C:\x\y" > Path.Combine(@"C:\x", @"\y") "\y"
似乎它们应该是相同的。
旧的FileSystemObject.BuildPath()无法以这种方式工作...
解决方案
回答
我不知道实际的细节,我想它会像我们可能会加入相对URI一样尝试加入。例如:
urljoin('/some/abs/path', '../other') = '/some/abs/other'
这意味着当我们将路径与前面的斜杠连接时,实际上是在将一个基础与另一个基础连接,在这种情况下,第二个将优先。
回答
从MSDN:
If one of the specified paths is a zero-length string, this method returns the other path. If path2 contains an absolute path, this method returns path2.
在示例中,path2是绝对的。
回答
这是一个哲学问题(也许只有Microsoft才能真正回答),因为它确实在按照文档中的说明进行操作。
System.IO.Path.Combine
"如果path2包含绝对路径,则此方法返回path2. "
这是来自.NET源的实际Combine方法。我们可以看到它调用CombineNoChecks,然后在path2上调用IsPathRooted并返回该路径(如果是)。
我不知道这是什么理由。我猜解决方案是从第二条路径的开头剥离(或者修剪)DirectorySeparatorChar;也许编写自己的Combine方法来执行该操作,然后调用Path.Combine()。
回答
这是.NET Reflector中用于Path.Combine方法的反汇编代码。检查IsPathRooted函数。如果第二个路径是根目录(以DirectorySeparatorChar开头),则按原样返回第二个路径。
public static string Combine(string path1, string path2) { if ((path1 == null) || (path2 == null)) { throw new ArgumentNullException((path1 == null) ? "path1" : "path2"); } CheckInvalidPathChars(path1); CheckInvalidPathChars(path2); if (path2.Length == 0) { return path1; } if (path1.Length == 0) { return path2; } if (IsPathRooted(path2)) { return path2; } char ch = path1[path1.Length - 1]; if (((ch != DirectorySeparatorChar) && (ch != AltDirectorySeparatorChar)) && (ch != VolumeSeparatorChar)) { return (path1 + DirectorySeparatorChar + path2); } return (path1 + path2); } public static bool IsPathRooted(string path) { if (path != null) { CheckInvalidPathChars(path); int length = path.Length; if ( ( (length >= 1) && ( (path[0] == DirectorySeparatorChar) || (path[0] == AltDirectorySeparatorChar) ) ) || ((length >= 2) && (path[1] == VolumeSeparatorChar)) ) { return true; } } return false; }
回答
我认为这是一个错误。问题在于存在两种不同类型的"绝对"路径。路径" d:\ mydir \ myfile.txt"是绝对路径,路径" \ mydir \ myfile.txt"也被视为"绝对路径",即使它缺少驱动器号。我认为正确的行为是,当第二个路径以目录分隔符开头(而不是UNC路径)时,在第一个路径前添加驱动器号。我建议编写自己的辅助包装函数,如果需要的话,该函数具有所需的行为。