ToUpperInvariant() – MSDN 在其建议上错了吗?

11
.NET Framework中使用字符串的最佳实践中,推荐使用StringComparison OrdinalIgnoreCase来处理不区分大小写的文件路径。我们称之为语句A。
我同意这一点,因为我可以在同一个目录中创建两个文件:
é.txt
é.txt

他们的文件名不同,第二个由 e 和修饰符组成,所以实际上有两个字母。(您可以尝试使用复制粘贴自行验证。)
如果采用不变区域比较(而不是序数比较),NTFS 将不允许这些文件,因为在同一篇文章中,他们解释说,在不变区域文化中 a + ̊ = å 但在 String.ToUpperInvariant() 的文章中有不同的建议:(语句 B。)

如果需要操作系统标识符(例如文件名、命名管道或注册表键)的小写或大写版本,请使用 ToLowerInvariant 或 ToUpperInvariant 方法。

我需要创建文件路径集合(实际上是 HashSet)来检测重复项。因此,如果我在创建映射时遵循语句 B,我可能会得到错误的结果,因为上述文件名 é.txté.txt 将被视为一个。我是否正确理解了 MSDN 中的语句 B 是误导性的?还是我漏掉了什么?

我即将建立一个图书馆,最好从一开始就没有已知的漏洞,因此我不想忽视这一点。

更新:

声明B似乎还有一个问题:不能实际使用ToLowerInvariant()。原因(我引用最佳实践文章):DO:在规范化字符串进行比较时使用ToUpperInvariant而不是ToLowerInvariant。实际原因:有一小部分字符无法往返,转换为小写会使这些字符无法使用。source


3
我不完全确定 "操作系统标识符的小写或大写版本" 是否意味着与 "将操作系统标识符明确映射为小写或大写版本" 相同。它还可以表示 "将操作系统标识符映射为非唯一的小写或大写版本,无论系统区域设置如何,都能以相同的方式工作"。 - O. R. Mapper
OT,但谁知道你的库会做什么:NTFS也允许在文件名中使用“:”、“*”或“?”。只是Windows不支持它。在Linux下,在NTFS上创建这样的文件非常容易。 - Thomas Weller
@O.R.Mapper - 阅读该声明的好方法......在这种情况下,它看起来很合乎逻辑。另一方面,他们可以不提到文件名或添加一个关于(非)唯一性的简短说明。 - miroxlav
1个回答

5

当您希望不区分大小写地比较字符串时,无论是大写还是小写都不正确。在两种变体中,都存在破坏这一点的字符。

进行不区分大小写的字符串比较的正确方法是使用其中一个不敏感的 StringComparison 选项(您知道的)。

以不区分大小写的方式使用数据结构的正确方法是使用 StringComparer.*IgnoreCase 之一。例如:

new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)

在将字符串添加到数据结构之前不要将其转换为大写。如果这样做,我会在任何代码审查中都无法通过。

如果您需要操作系统标识符的小写或大写版本

您不需要这样做。该语句不适用于您的情况。


因此,在NTFS文件名的情况下,这意味着new HashSet<string>(StringComparer.OrdinalIgnoreCase)(或者只是OrdinalCase,具体取决于在特定情况下如何切换NTFS大小写敏感性)。 - miroxlav
我不知道NTFS使用哪种比较方式。它可以进行配置。每个NTFS卷上都有一个隐藏文件,用于存储Unicode大小写映射表。我猜它可能是任意的。不确定实际情况如何。 - usr
是的,我知道...这意味着我们可能需要像NtfsIgnoreCase比较这样的东西,根据隐藏的$UpCase文件的内容进行工作 :) - miroxlav
请参考我的这个回答(简而言之:对于文件名使用OrdinalIgnoreCase)。 - Lucas Trzesniewski
@LucasTrzesniewski - 我确实看到过 :) 还有 这个这个 值得注意的问答。最后我使用了 Dictionary(Of T1, T2)(StringComparer.OrdinalIgnoreCase) 来满足我的特定需求。 - miroxlav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接