必须用Path.Combine,字符串拼接在.NET 5+中等同埋雷;它自动适配平台分隔符、清理冗余斜杠、忽略空段、拒绝null,而手动拼接易致转义错误、跨平台失效及路径错位。

必须用 Path.Combine,字符串拼接路径在 .NET 5+ 中等于主动触发运行时崩溃。
为什么 Path.Combine 不能被字符串拼接替代
手动写 "C:\logs\" + fileName 或 dir + "/" + file 会直接暴露平台差异和转义风险:"C:logspp.log" 中的 p 被识别为非法转义序列,编译失败;Linux 容器里 "C:\data" 根本无法解析。而 Path.Combine 内部自动适配 Path.DirectorySeparatorChar,同时清理冗余分隔符、忽略空段、拒绝 null 参数(抛 ArgumentNullException)。
常见错误现象:
-
File.Exists("C:config.json")返回false,实际是因为它等价于C:currentconfig.json(当前工作目录前缀被隐式补上) -
Path.Combine("a", "b", "C:\root", "file.txt")结果是"C:\root\file.txt",前面参数全丢——这是设计行为,不是 bug
实操建议:
- 永远传多个参数:
Path.Combine(baseDir, "config", "app.json"),别只传两个 - 若输入可能含绝对路径,先用
Path.IsPathRooted(userInput)判断,再决定是否Combine - 不校验输入就传
null,必炸;空字符串会被跳过,但不意味着安全,仍需业务层校验
Path.GetFullPath 的基准目录陷阱
Path.GetFullPath("config.json") 不读磁盘,只以 Environment.CurrentDirectory 为起点做字符串展开。这个值在 dotnet run、IIS、Windows 服务、Docker 容器中极易漂移——调试时指向项目根,发布后可能变成 C:WindowsSystem32。
正确做法是显式指定基准目录:
- .NET 5+ 推荐:
Path.GetFullPath("config.json", AppContext.BaseDirectory) - 旧版本兼容写法:
Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "config.json"))
必须捕获异常:
-
ArgumentException:含<、>、|、?、*等非法字符 -
IOException:路径长度超 Windows 默认 260 字符限制(尤其在深度嵌套或长文件名场景)
Path.GetFileName 和 Path.GetExtension 的末尾分隔符敏感性
这两个方法只看「最后一个分隔符位置」。如果路径以 或 / 结尾,它们就认为这是目录路径,返回空字符串。
错误示例:
-
Path.GetFileName(@"C:data eport")→""(不是"report") -
Path.GetExtension("archive.")→"."(不是空)
实操建议:
- 提取文件名前,先用
Path.GetFullPath归一化,或确保输入不含尾部分隔符 - 不要靠
lastIndexOf('\')手动切——Path类就是为此设计的,但得用对 - UNC 路径如
@"\servershareile.txt"可直接喂给这些方法,无需特殊处理
相对路径(..)必须配 Path.GetFullPath
Path.Combine("C:\app", "..\config\settings.xml") 输出仍是 "C:\app\..\config\settings.xml"——它不做解析,只拼接。要得到真实物理路径,必须再套一层 Path.GetFullPath。
典型误用:
- 直接用
Directory.GetParent(path).FullName处理含..的路径,结果仍是字面量,没归一化 - 把
Path.Combine和Path.GetFullPath顺序搞反,先GetFullPath再Combine,导致基准错乱
推荐组合:
-
Path.GetFullPath(Path.Combine(baseDir, userInput))—— 最稳,覆盖相对路径、..、.、多余斜杠 - 若仅需纯字符串规整(不访问磁盘),可用
Path.GetRelativePath,但极少需要
跨平台部署时,最容易被忽略的是:你本地测试通过的路径逻辑,在 Linux 容器里因 CurrentDirectory 漂移或 IsPathRooted 判断失效,直接返回空或错路径——这些都不是异常,而是静默错误。


















