如何System.String妥善包裹的情况下,insensitivy? [英] How can System.String be properly wrapped for case-insensitivy?
问题描述
此问题的没有的有关管理Windows路径名;我以前只作为一个不区分大小写的具体例子。 (我如果我改变的例子,现在,一大堆的意见将是毫无意义的。)
This question is not about managing Windows pathnames; I used that only as a specific example of a case-insensitive string. (And I if I change the example now, a whole bunch of comments will be meaningless.)
这可以类似于<一href="http://stackoverflow.com/questions/32146065/possible-to-create-case-insensitive-string-class">Possible创建不区分大小写字符串类?,但没有很多讨论存在。另外,我真的不关心紧密的语言集成的字符串
享有或 System.String
的性能优化
This may be similar to Possible to create case insensitive string class?, but there isn't a lot of discussion there. Also, I don't really care about the tight language integration that string
enjoys or the performance optimizations of System.String
.
比方说,我用了很多的Windows路径名这是(通常)不区分大小写(我不是真正关心的是像实际路径的许多细节\
VS /
, \\\\
是一样的 \
,文件://
网址, ..
等)。一个简单的包装可能是:
Let's say I use a lot of Windows pathnames which are (normally) case-insensitive (I'm not actually concerned with the many details of actual paths like \
vs. /
, \\\\
being the same as \
, file://
URLs, ..
, etc.). A simple wrapper might be:
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 的可能应该执行;但上面好像够讨论的目的。
Yes, all/most of the interfaces on System.String should probably be implemented; but the above seems like enough for discussion purposes.
我现在可以这样写:
var p1 = new WindowsPathname(@"c:\foo.txt");
var p2 = new WindowsPathname(@"C:\FOO.TXT");
bool areEqual = p1.Equals(p2); // true
这让我谈 WindowsPathname
在我的code,而不是实施细节如 StringComparison.OrdinalIgnoreCase
。 (是的,这的的具体的类也可以扩展到处理 \
VS /
使 C:/foo.txt 的将等于的 C:\ foo.txt的的,但是这不是这个问题点)。此外,这个类(有更多的接口)将不区分大小写,当实例添加到收藏;那就没有必要指定一个的IEqualityComparer
。最后,像这样的一个特定的类也可以更容易地prevent非意识操作,如一个文件系统路径比较一个注册表项。
This allows me to "talk about" WindowsPathname
s in my code rather than a implementation detail like StringComparison.OrdinalIgnoreCase
. (Yes, this specific class could also be extended to handle \
vs /
so that c:/foo.txt would be equal to C:\FOO.TXT; but that's not the point of this question.) Furthermore, this class (with additional interfaces) will be case-insensitive when instances are added to collections; it would not necessary to specify an IEqualityComparer
. Finally, a specific class like this also makes it easier to prevent "non-sense" operations such as comparing a file system path to a registry key.
的问题是:这样的做法是成功的?是否有任何严重的和/或细微的瑕疵或其他陷阱?(同样,不必做,试图建立一个不区分大小写字符串类,而不是管理Windows路径名。)
The question is: will such approach be successful? Are there any serious and/or subtle flaws or other "gotchas"? (Again, having to do with trying to setup a case-insensitive string class, not managing Windows pathnames.)
推荐答案
我将创建一个不可改变的结构持有一个字符串,将字符串中的构造标准的情况下(如小写)。 然后,你也可以添加隐式运算符来简化创建和覆盖比较运营商。 我认为这是实现该问题的最简单的方法,再加上你得到的只是一个小的开销(转换只在构造函数)。
I would create an immutable struct that hold a string, converting the string in the constructor to a standard case (e.g. lowercase). Then you could also add the implicit operator to simplify the creation and override the compare operators. I think this is the simplest way to achieve the behaviour, plus you get only a small overhead (the conversion is only in the constructor).
这里的code:
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
这适用于收藏为好。
这篇关于如何System.String妥善包裹的情况下,insensitivy?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!