简体   繁体   中英

How to override general comparison for two strings in C#

I've a question like the link below but much more complicated: Ignoring accented letters in string comparison

I have a dictionary and some values inside like:

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

and for inserting new elements into the dictionary, as the sames codes, I wrote this:

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

But when I want to check the existence of this value : {[Ministère de l'economie, 139]} it returns it doesn't exist.

How can I implement this response to my code?

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

On the other way, as the title of my question, how can I overwrite the general (or the main) string comparison method in my application?

So, combining with the linked answer for removal of accents and diacritics , you can make an IEqualityComparer<string> to supply to your dictionary:

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

Now, construct your dictionary using an instance of this comparer:

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

and try adding something accented:

myDic["Aimée"] = 1;

...and read it back out, without the accent:

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

Starting from .NET 4.6 there are some interesting overloads of CompareInfo , so that the first solution suggested in https://stackoverflow.com/a/368850/613130 is usable in an 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
}

and then

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM