【发布时间】:2016-01-07 11:09:20
【问题描述】:
这个问题不是关于管理 Windows 路径名的;我仅将其用作不区分大小写字符串的特定示例。 (而且我现在换个例子,一大堆cmets就没有意义了。)
这可能类似于Possible to create case insensitive string class?,但那里没有太多讨论。另外,我并不关心string 所享受的紧密语言集成或System.String 的性能优化。
假设我使用了很多(通常)不区分大小写的 Windows 路径名(我实际上并不关心实际路径的许多细节,例如 \ 与 /、\\\\ 相同如\、file:// URL、.. 等)。一个简单的包装器可能是:
sealed class WindowsPathname : IEquatable<WindowsPathname> /* TODO: more interfaces from System.String */
{
public WindowsPathname(string path)
{
if (path == null) throw new ArgumentNullException(nameof(path));
Value = path;
}
public string Value { get; }
public override int GetHashCode()
{
return Value.ToUpperInvariant().GetHashCode();
}
public override string ToString()
{
return Value.ToString();
}
public override bool Equals(object obj)
{
var strObj = obj as string;
if (strObj != null)
return Equals(new WindowsPathname(strObj));
var other = obj as WindowsPathname;
if (other != null)
return Equals(other);
return false;
}
public bool Equals(WindowsPathname other)
{
// A LOT more needs to be done to make Windows pathanames equal.
// This is just a specific example of the need for a case-insensitive string
return Value.Equals(other.Value, StringComparison.OrdinalIgnoreCase);
}
}
是的,System.String 上的所有/大部分接口可能都应该实现;但以上内容似乎足以用于讨论目的。
我现在可以写了:
var p1 = new WindowsPathname(@"c:\foo.txt");
var p2 = new WindowsPathname(@"C:\FOO.TXT");
bool areEqual = p1.Equals(p2); // true
这让我可以在我的代码中“谈论”WindowsPathnames,而不是像StringComparison.OrdinalIgnoreCase 这样的实现细节。 (是的,这个特定的类也可以扩展为处理\和/,这样c:/foo.txt就等于C: \FOO.TXT; 但这不是这个问题的重点。)此外,当将实例添加到集合时,此类(带有附加接口)将不区分大小写;没有必要指定IEqualityComparer。最后,像这样的特定类还可以更轻松地防止“无意义”操作,例如将文件系统路径与注册表项进行比较。
问题是:这种方法会成功吗?是否有任何严重和/或微妙的缺陷或其他“陷阱”?(再次,与尝试设置不区分大小写的字符串类有关,而不是管理 Windows 路径名。)
【问题讨论】:
-
请注意,更多的 '/' 或 '\' 可以使您的窗口路径不同的字符串但等于窗口路径。检查此路径规范化以了解更多信息stackoverflow.com/questions/2281531/…
-
我不确定在必要时使用字符串不敏感比较有什么问题,因为您唯一关心它的时间是在比较期间。好像用大锤敲钉子,使用现有框架代码很容易解决问题的开销很大。
-
这是一个大错误,从不区分大小写的比较开始严重依赖于文化,一个可以更改的属性,并以确切的路径名比较和解析规则作为文件系统驱动程序实现细节结束。 .NET 没有这个的基本原因。正确执行此操作的唯一方法是同时访问磁盘并检查您是否获得相同的文件系统路径。
-
为字符串添加一个扩展方法也很简单,比如
public static bool InsensitveCompare(this string a, string b) { return string.Compare(a, b, true) == 0; }但是你的观点只是一个例子,你在哪里停下来?InsensitiveFirstNameInsenstiveLastName,InsensitiveDog,InsensitiveCat令人作呕。对于一个不断增长的问题,它只是膨胀,只需一行代码即可解决。 -
如果你尝试过,你不可能选择一个更糟糕的例子:)