gpt4 book ai didi

c# - 如何正确包装 System.String 以不区分大小写?

转载 作者:太空狗 更新时间:2023-10-29 18:28:54 25 4
gpt4 key购买 nike

这个问题不是关于管理 Windows 路径名的;我仅将其用作不区分大小写字符串的具体示例。 (如果我现在更改示例,那么一大堆评论将毫无意义。)


这可能类似于 Possible to create case insensitive string class? ,但那里没有太多讨论。此外,我并不真正关心 string 享有的紧密语言集成或 System.String 的性能优化。

假设我使用了很多(通常)不区分大小写的 Windows 路径名(我实际上并不关心实际路径的许多细节,例如 \/, \\\\\, file:// URLs, .. , ETC。)。一个简单的包装器可能是:

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 上的所有/大部分接口(interface)可能应该被实现;但以上内容似乎足以进行讨论。

我现在可以写:

var p1 = new WindowsPathname(@"c:\foo.txt");
var p2 = new WindowsPathname(@"C:\FOO.TXT");
bool areEqual = p1.Equals(p2); // true

这使我可以在我的代码中“谈论”WindowsPathname,而不是像 StringComparison.OrdinalIgnoreCase 这样的实现细节。 (是的,这个特定的类也可以被扩展来处理\ vs / 这样c:/foo.txt 将等于 C:\FOO.TXT;但这不是这个问题的重点。)此外,当将实例添加到集合中时,此类(具有附加接口(interface))将不区分大小写;没有必要指定 IEqualityComparer。最后,像这样的特定类还可以更轻松地防止“无意义”操作,例如将文件系统路径与注册表项进行比较。

问题是:这种方法会成功吗?是否存在任何严重和/或微妙的缺陷或其他“陷阱”?(同样,与尝试设置不区分大小写的字符串类有关,而不是管理 Windows 路径名。)

最佳答案

我会创建一个包含字符串的不可变结构,将构造函数中的字符串转换为标准大小写(例如小写)。然后您还可以添加隐式运算符以简化创建并覆盖比较运算符。我认为这是实现该行为的最简单方法,而且开销很小(转换仅在构造函数中进行)。

代码如下:

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);
}
}

用法如下:

CaseInsensitiveString a = "STRING";
CaseInsensitiveString b = "string";

// a == b --> true

这也适用于集合。

关于c# - 如何正确包装 System.String 以不区分大小写?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33039324/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com