这个问题不是关于管理Windows路径名; 我仅将其用作不区分大小写的字符串的特定示例.(如果我现在改变这个例子,那么一大堆评论将毫无意义.)
这可能类似于可能创建不区分大小写的字符串类?,但那里没有很多讨论.此外,我并不真正关心所string享有的紧密语言集成或性能优化System.String.
比方说,我用了很多这些(正常)不区分大小写Windows路径名的(我不是真正关心的实际像路径的很多细节\对/,\\\\是一样的\,file://网址..等).一个简单的包装器可能是:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
是的,可能应该实现System.String上的所有/大多数接口; 但上述内容似乎足以供讨论之用.
我现在可以写:
var p1 = new WindowsPathname(@"c:\foo.txt");
var p2 = new WindowsPathname(@"C:\FOO.TXT");
bool areEqual = p1.Equals(p2); // true
Run Code Online (Sandbox Code Playgroud)
这允许我WindowsPathname在我的代码中"讨论" 而不是像实现细节那样StringComparison.OrdinalIgnoreCase.(是的,这个特定的类也可以扩展为处理\vs,/这样c:/foo.txt将等于C:\ FOO.TXT ;但这不是这个问题的重点.)此外,这个类(带有额外的接口) )当实例添加到集合时,将不区分大小写; 没有必要指定一个IEqualityComparer.最后,像这样的特定类也可以更容易地防止"无意义"操作,例如将文件系统路径与注册表项进行比较.
问题是:这种方法会成功吗?是否有任何严重和/或微妙的缺陷或其他"陷阱"?(再次,与尝试设置不区分大小写的字符串类,而不是管理Windows路径名有关.)
小智 8
我将创建一个包含字符串的不可变结构,将构造函数中的字符串转换为标准大小写(例如小写).然后,您还可以添加隐式运算符以简化创建并覆盖比较运算符.我认为这是实现行为的最简单方法,而且只需要很小的开销(转换仅在构造函数中).
这是代码:
public struct CaseInsensitiveString
{
private readonly string _s;
public CaseInsensitiveString(string s)
{
_s = s.ToLowerInvariant();
}
public static implicit operator CaseInsensitiveString(string d)
{
return new CaseInsensitiveString(d);
}
public override bool Equals(object obj)
{
return obj is CaseInsensitiveString && this == (CaseInsensitiveString)obj;
}
public override int GetHashCode()
{
return _s.GetHashCode();
}
public static bool operator ==(CaseInsensitiveString x, CaseInsensitiveString y)
{
return x._s == y._s;
}
public static bool operator !=(CaseInsensitiveString x, CaseInsensitiveString y)
{
return !(x == y);
}
}
Run Code Online (Sandbox Code Playgroud)
这是用法:
CaseInsensitiveString a = "STRING";
CaseInsensitiveString b = "string";
// a == b --> true
Run Code Online (Sandbox Code Playgroud)
这也适用于收藏.