是否有 C# 不区分大小写的等于运算符?

Posted

技术标签:

【中文标题】是否有 C# 不区分大小写的等于运算符?【英文标题】:Is there a C# case insensitive equals operator? 【发布时间】:2010-10-12 11:41:36 【问题描述】:

我知道以下是区分大小写的:

if (StringA == StringB) 

那么有没有一个运算符会以不敏感的方式比较两个字符串?

【问题讨论】:

Caselessly comparing strings in C#的可能重复 如果有人偶然发现这个问题正在寻找字典的不区分大小写比较,请在此处查看此问题:Case insensitive access for generic dictionary 真的很好;说要定义一个对应的~= 来并行== 作为不区分大小写的版本。 如果微软开发者看到了这一点,我认为在下一个版本的 csharp 中需要一个不区分大小写的运算符。这个 string.Equal() 很长。 【参考方案1】:

//您可以通过以下方式使其不区分大小写 s1.ToLower() == s2.ToLower();

【讨论】:

【参考方案2】:

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

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

【讨论】:

虽然我喜欢简洁的 looking 用法语法,但它有点误导(IgnoreCase vs IgnoreCaseString)和模棱两可(Java 选择隐式拆箱与隐式装箱,所以我believe 这在 Java 中不起作用,其中隐式转换回字符串)。这会产生 2 个新对象的内存开销,每次比较的调用树执行会跳转到显示的用例的几个嵌套方法调用中。也就是说,在大多数情况下,性能可能已经足够好了。 虽然这是一个聪明的想法,但从可维护性的角度来看它并不明智。您实际上是在创建代理字符串类型,而不是使用系统的内置字符串类型。后继程序员不会一眼就明白发生了什么,然后他/她会骂你。使用 string.Equals() 并没有那么糟糕,大多数人都会明白它在做什么。【参考方案3】:

其他答案在这里完全有效,但不知何故,输入StringComparison.OrdinalIgnoreCase 并使用String.Compare 需要一些时间。

我编写了简单的字符串扩展方法,您可以在其中指定比较是区分大小写还是不区分大小写的布尔值 - 请参阅以下答案:

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

【讨论】:

【参考方案4】:

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

我测试了这两种方法的性能,顺序忽略大小写字符串比较快了 9 倍以上!它也比将字符串转换为小写或大写更可靠(查看土耳其语 i 问题)。所以总是使用String.Equals 方法来比较字符串是否相等:

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

如果您想执行特定于文化的字符串比较,您可以使用以下代码:

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

请注意,第二个示例使用当前文化的字符串比较逻辑,这使得它比第一个示例中的“序数忽略大小写”比较慢,所以如果您不需要任何文化特定的字符串比较逻辑并且您追求最佳性能,请使用“序数忽略大小写”比较。

欲了解更多信息,read the full story on my blog。

【讨论】:

不要建议 ToLowerToLowerInvariant:它们创建内存只是为了执行比较,并且它们可能会在新字符集添加到 unicode 时失败。 ToUpper 因土耳其语“i”等而失败;没有理由 ToLower 在未来不会因为类似的原因而失败。 @antiduh,感谢您的评论。我们大多数人都知道这些潜在的问题,互联网上的许多教程都以土耳其语“i”为例。正如您在我的帖子中看到的,我不建议使用ToLowerToLowerInvariant 方法,我只是想展示String.Equals 方法的效率有多高。 “我们大多数人都知道这些潜在的问题,互联网上的许多教程都以土耳其语 'i' 为例” - 没有足够的人,你仍然提到它作为第二个回答中的句子。此外,您的 answer 没有包含足够的理由来永远不要使用它 - 您只是提到了性能;性能并不总是最重要的。因此,您目前违反了帮助中心指南;指向外部网站的链接很好,但您没有充分总结内容(土耳其语“我”问题)。 SO 不是您的广告平台。【参考方案5】:

我很习惯在这些比较方法的末尾打字:, 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 上检查 null。

【讨论】:

这是否与当前 .NET Framework 版本中的此内置方法相同? docs.microsoft.com/en-gb/dotnet/api/… 看起来如此。看起来更高版本的 .net 现在包含了这个。 从 .NET 4.5 和所有 .NET Core 版本开始可用。【参考方案6】:

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

但您需要确保 StringA 不为空。所以可能更好地使用:

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

按照约翰的建议

编辑:修正错误

【讨论】:

【参考方案7】:

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

StringComparer Properties

例如,您可以调用

StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)

StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)

它比采用StringComparison 参数的string.Equalsstring.Compare 重载要干净一些。

【讨论】:

【参考方案8】:
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) 

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

【讨论】:

如果当前或所需的文化有特殊的大写规则,那么不变量可能不是一个好主意。 这是否会为每个字符串创建一个新副本?如果是这样,那是个坏主意。 如果其中一个(或两个)字符串为空,也会抛出异常。 性能方面,这不是一个好的解决方案,因为您还将在这里创建 2 个新的字符串实例。【参考方案9】:
string.Compare(string1, string2, true)

【讨论】:

【参考方案10】:

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

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

我相信它会改变等号运算符比较字符串的方式。

【讨论】:

是的,至少可以说这完全不是您想要做的,除非您希望所有字符串比较都不区分大小写。但我认为它改变了等号运算符的行为。【参考方案11】:

你可以使用

if (stringA.equals(StringB, StringComparison.CurrentCultureIgnoreCase))

【讨论】:

【参考方案12】:
string.Equals(StringA, StringB, StringComparison.CurrentCultureIgnoreCase);

【讨论】:

【参考方案13】:
System.Collections.CaseInsensitiveComparer

System.StringComparer.OrdinalIgnoreCase

【讨论】:

这会影响整个应用程序吗? 在哪里可以找到更多信息。这是否意味着我可以使用 == 进行不区分大小写的匹配?【参考方案14】:

试试这个:

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

【讨论】:

您可以通过尝试接近提问者想要的内容来丰富您的答案。在这种情况下,您可以发布一个快速扩展方法。 如:public static bool EqualsCaseInsensitive(this string a, string b) return string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase); 如果要进行文化敏感比较,请使用此方法。如果您只是想确保“文件”和“文件”都被接受,请使用“OrdinalIgnoreCase”,否则您的代码可能无法在土耳其语言环境等地方运行。有关详细信息,请参阅moserware.com/2008/02/does-your-code-pass-turkey-test.html 啊这真是太糟糕了!我的键盘会磨损。我可以使用“if A$=B$ then goto 10”的日子已经一去不复返了 @Sanjay Manohar 然后编写一个自定义运算符 - 我会推荐一个更好的键盘。

以上是关于是否有 C# 不区分大小写的等于运算符?的主要内容,如果未能解决你的问题,请参考以下文章

Redshift SQL 可以执行不区分大小写的正则表达式求值吗?

mysql模糊查询区分大小写

在 C# 中具有字符串键类型的不区分大小写字典

LIKE运算符是否与MSSQL Server区分大小写?

映射不区分大小写 - 代码优先 - 实体框架

c#中不区分大小写的XML解析器