是否存在C#不区分大小写的equals运算符?


156

我知道以下内容区分大小写:

if (StringA == StringB) {

那么,是否有一个运算符将以不敏感的方式比较两个字符串?



如果有人偶然发现此问题以查找Dictionary <string,int>的不区分大小写的比较,请在此处查看以下问题:通用词典的不区分大小写访问
Robotnik 2014年

真的很好。说将对应~=于parallel 定义==为不区分大小写的版本。
eidylon

如果Microsoft开发人员看到了这一点,我认为在下一版本的csharp中需要不区分大小写的运算符。此string.Equal()很长。
Rez.Net

Answers:


288

试试这个:

string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);

我是一个相对于StackOverflow的新手-您能解释一下添加链接的意思吗?您是指MSDN文档吗?
John Feminella 09年

55
如果要进行文化敏感的比较,请使用此方法。如果只想确保同时接受“ FILE”和“ file”,请使用“ OrdinalIgnoreCase”,否则您的代码在土耳其语区域设置等地方可能无法正常工作。有关更多信息,请参见moserware.com/2008/02/does-your-code-pass-turkey-test.html
Jeff Moser 2009年

10
不知道塞缪尔在说什么...这个答案是完美的。其正确和不言自明。它不需要参考。+1
柔道航行

3
哎呀,这真可怕!我的键盘会磨损。我可以使用“ if A$=B$ then goto 10” 的日子已经一去不复返了
Sanjay Manohar 2012年

9
@Sanjay Manohar然后编写一个自定义运算符-我建议使用更好的键盘。
Rushyo 2012年

37

比较2个忽略字母大小写的字符串的最佳方法是使用String.Equals静态方法,指定一个有序的忽略大小写字符串比较。这也是最快的方法,比将字符串转换为小写或大写并在此之后进行比较要快得多。

我测试了这两种方法的性能,顺序的忽略大小写字符串比较的速度快了9倍以上!它比将字符串转换为小写或大写更为可靠(请查看Turkish i问题)。因此,请始终使用String.Equals方法比较字符串是否相等:

String.Equals(string1, string2, StringComparison.OrdinalIgnoreCase);

如果要执行区域性特定的字符串比较,可以使用以下代码:

String.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase);

请注意,第二个示例使用当前区域性的字符串比较逻辑,这使其比第一个示例中的“常规忽略大小写”比较慢,因此,如果您不需要任何特定于区域性的字符串比较逻辑,则可以达到最佳性能后,请使用“常规忽略大小写”比较。

有关更多信息,请阅读我的博客上的全文


1
不要建议ToLowerToLowerInvariant:它们只是为了进行比较而创建内存,并且可能会在将新字符集添加到unicode时失败。ToUpper由于土耳其语“ i”等原因而失败;ToLower出于类似原因,将来没有理由不会失败。
antiduh

@antiduh,谢谢您的评论。我们大多数人都意识到了这些潜在问题,互联网上的许多教程都以土耳其语“ i”为例。如您在我的帖子中看到的,我不建议使用ToLowerToLowerInvariant方法,我只是想展示该String.Equals方法的效率高得多。
帕维尔·弗拉多夫

3
“我们大多数人都意识到了这些潜在的问题,互联网上的许多教程都以土耳其语'i'为例”-人数不够,您仍将其作为答案中的第二句话。此外,您的答案没有足够的理由不使用它-您仅提及性能;性能并不总是最终的优先事项。因此,您当前违反了帮助中心的准则;指向外部站点的链接很好,但是您没有对内容进行足够的概括(土耳其语“ i”问题)。SO不是您的广告平台。
antiduh

20

StringComparer静态类上有许多属性可以返回比较器,以获取您可能需要的任何区分大小写的类型:

StringComparer 物产

例如,您可以致电

StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)

要么

StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)

它比接受参数的string.Equalsstring.Compare重载要干净一些StringComparison


15
System.Collections.CaseInsensitiveComparer

要么

System.StringComparer.OrdinalIgnoreCase

这会影响整个应用程序吗?
GateKiller

3
在哪里可以找到更多信息。这是否意味着我可以将==用于不区分大小写的匹配?
GateKiller 2009年

9
string.Equals(StringA, StringB, StringComparison.CurrentCultureIgnoreCase);

8

要么

if (StringA.Equals(StringB, StringComparison.CurrentCultureIgnoreCase)) {

但是您需要确保StringA不为null。因此,最好使用tu:

string.Equals(StringA , StringB, StringComparison.CurrentCultureIgnoreCase);

如约翰建议

编辑:更正了该错误



3

操作员?不,但是我认为您可以更改文化,以使字符串比较不区分大小写。

// you'll want to change this...
System.Threading.Thread.CurrentThread.CurrentCulture
// and you'll want to custimize this
System.Globalization.CultureInfo.CompareInfo

我相信它将改变equals运算符比较字符串的方式。


是的,至少可以说这不是您要执行的操作,除非您希望所有字符串比较不区分大小写。但是我认为这改变了equals运算符的行为。
约翰·莱德格伦

3

这里有一个简化语法的想法:

public class IgnoreCase
{
    private readonly string _value;

    public IgnoreCase(string s)
    {
        _value = s;
    }

    protected bool Equals(IgnoreCase other)
    {
        return this == other;
    }

    public override bool Equals(object obj)
    {
        return obj != null &&
               (ReferenceEquals(this, obj) || (obj.GetType() == GetType() && this == (IgnoreCase) obj));
    }

    public override int GetHashCode()
    {
        return _value?.GetHashCode() ?? 0;
    }

    public static bool operator ==(IgnoreCase a, IgnoreCase b)
    {
        return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
    }

    public static bool operator !=(IgnoreCase a, IgnoreCase b)
    {
        return !(a == b);
    }

    public static implicit operator string(IgnoreCase s)
    {
        return s._value;
    }

    public static implicit operator IgnoreCase(string s)
    {
        return new IgnoreCase(s);
    }
}

可用方式如下:

Console.WriteLine((IgnoreCase) "a" == "b"); // false
Console.WriteLine((IgnoreCase) "abc" == "abC"); // true
Console.WriteLine((IgnoreCase) "Abc" == "aBc"); // true
Console.WriteLine((IgnoreCase) "ABC" == "ABC"); // true

虽然我喜欢外观简洁的用法语法,但它有点误导(IgnoreCasevs IgnoreCaseString)和模棱两可(Java选择隐式拆箱与隐式装箱,因此我认为在Java中将隐式转换回字符串后,该方法将不起作用)。这就创建了2个新对象的内存开销,每次比较的调用树执行都会跳转到显示的使用情况的几个嵌套方法调用中。也就是说,在大多数情况下,性能可能足够好。
Arkaine55

尽管这是一个聪明的主意,但从可维护性的角度来看,这并不是真正的明智之举。您实际上是在创建代理字符串类型,而不是使用系统的内置字符串类型。后来的程序员将一眼不明白发生了什么,然后他/她将对您发怒。使用string.Equals()并不是真的很糟糕,大多数人都会理解它在做什么。
ntcolonel

1

我习惯在这些比较方法的结尾处​​键入: , StringComparison.

所以我做了一个扩展。

namespace System
{   public static class StringExtension
    {
        public static bool Equals(this string thisString, string compareString,
             StringComparison stringComparison)
        {
            return string.Equals(thisString, compareString, stringComparison);
        }
    }
}

只需注意,您将需要thisString在调用ext之前检查null 。


1
这与当前.NET Framework版本中的此内置方法相同吗? docs.microsoft.com/en-gb/dotnet/api/…–
伯纳德·范德·

1
看来是这样。看起来.net的更高版本现在包含了此功能。
Valamas

从.NET 4.5和所有.NET Core版本开始可用。
伯纳德·范德·贝克


0
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {

人们报告ToUpperInvariant()比ToLowerInvariant()更快。


1
如果当前或期望的文化对上层套管有特殊规定,那么不变性可能不是一个好主意。
OregonGhost

这会为每个字符串创建一个新副本吗?如果是这样,那就不好了。
cjk

1
如果一个(或两个)字符串都为空,这也会引发异常。
tvanfosson

3
从性能角度来看,这不是一个很好的解决方案,因为您还将在此处创建2个新的字符串实例。
Frederik Gheysels 09年

0

其他答案在这里完全有效,但是以某种方式键入StringComparison.OrdinalIgnoreCase和使用也需要一些时间String.Compare

我已经编码了简单的String扩展方法,您可以在其中指定比较是否区分大小写或使用布尔值区分大小写-参见以下答案:

https://stackoverflow.com/a/49208128/2338477

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.