如何覆盖 C# 中两个字符串的一般比较

How to override general comparison for two strings in C#

我有一个类似下面 link 的问题,但要复杂得多: Ignoring accented letters in string comparison

我有一本字典,里面有一些值,例如:

{[Ministère de l'économie, 139]}
{[Ministère des finances, 114]}

为了向字典中插入新元素,作为相同的代码,我这样写:

if (!dict.ContainsKey(str))
{  dict.Add(str, Convert.ToDouble(number)); }

但是当我想检查这个值是否存在时: {[Ministère de l'economie, 139]} 它 returns 它不存在。

如何实现对我的代码的响应?

string.Compare(s1, s2, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace); 

另一方面,正如我的问题标题,我如何在我的应用程序中覆盖一般(或主要)字符串比较方法?

所以,结合 linked answer for removal of accents and diacritics,你可以制作一个 IEqualityComparer<string> 来提供给你的字典:

public class IgnoreAccentsAndDiacriticsComparer:IEqualityComparer<string>
{
    public bool Equals(string left, string right)
    {
        if(left == null && right == null){ return true; }
        if(left == null || right == null){ return false; }
        return string.Equals(RemoveDiacritics(left), RemoveDiacritics(right));
    }

    public int GetHashCode(string txt)
    {
        return RemoveDiacritics(txt).GetHashCode();
    }

    static string RemoveDiacritics(string text)
    {
        string formD = text.Normalize(NormalizationForm.FormD);
        StringBuilder sb = new StringBuilder();

        foreach (char ch in formD)
        {
            UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(ch);
            if (uc != UnicodeCategory.NonSpacingMark)
            {
                sb.Append(ch);
            }
        }

        return sb.ToString().Normalize(NormalizationForm.FormC);
    }
}

现在,使用这个比较器的一个实例构建你的字典:

var myDic = new Dictionary<string, int>(new IgnoreAccentsAndDiacriticsComparer())

并尝试添加重音符号:

myDic["Aimée"] = 1;

...然后读回,不带重音:

Console.WriteLine(myDic["Aimee"]); //ŵôõ!

从 .NET 4.6 开始,CompareInfo 有一些有趣的重载,因此 中建议的第一个解决方案可用于 IEqualityComparer<string>:

public class StringComparerIgnoreDiacritics : IEqualityComparer<string>
{
    public static readonly StringComparerIgnoreDiacritics CurrentCulture = new StringComparerIgnoreDiacritics(CultureInfo.CurrentCulture.CompareInfo);

    public readonly CompareInfo CompareInfo;

    public StringComparerIgnoreDiacritics(CompareInfo compareInfo)
    {
        CompareInfo = compareInfo;
    }

    #region IEqualityComparer<string> Members

    public bool Equals(string x, string y)
    {
        return CompareInfo.Compare(x, y, CompareOptions.IgnoreNonSpace) == 0;
    }

    public int GetHashCode(string obj)
    {
        return CompareInfo.GetHashCode(obj, CompareOptions.IgnoreNonSpace);
    }

    #endregion
}

然后

var myDic = new Dictionary<string, int>(var myDic = new Dictionary<string, int>(new IgnoreAccentsAndDiacriticsComparer()).CurrentCulture);