不区分大小写将字符串与非字符串进行比较

Bry*_*ner 2 c# string equals case-insensitive

我创建了一个C#结构,它可以透明地处理不区分大小写的字符串比较.例如:

List<IString> list = new List<IString>();
list.Add("help");
Assert.IsTrue(list.Contains("Help"));
Run Code Online (Sandbox Code Playgroud)

要么

Dictionary<IString, string> dict = new Dictionary<IString, string>();
dict["Help"] = "thanks!";
Assert.AreEqual("thanks!", dict["hELP"]);
Run Code Online (Sandbox Code Playgroud)

但是我无法弄清楚的一件事(也许是不可能的)是如何让类字符串在.Equals(object)中很好地发挥作用:

IString A1 = "A";
string A2 = "a";
Assert.AreEqual(A1, A2, "This passes");
Assert.AreEqual(A2, A1, "This fails");
Run Code Online (Sandbox Code Playgroud)

这是代码:

using System;
using System.Collections.Generic;

namespace Util
{
    /// <summary>
    /// Case insensitive wrapper for the string class
    /// </summary>
    public struct IString :
        IComparer<IString>,
        IComparable,
        IComparable<IString>,
        IComparable<string>,
        IEquatable<string>,
        IEquatable<IString>
    {
        private const StringComparison icase = StringComparison.OrdinalIgnoreCase;

        public readonly string Value;
        public IString(string Value)
        {
            this.Value = Value;
        }

        public bool Equals(string Other)
        {
            return string.Equals(Value, Other, icase);
        }
        public bool Equals(IString Other)
        {
            return string.Equals(Value, Other.Value, icase);
        }
        public override bool Equals(object obj)
        {
            if (obj is IString || obj is string)
            {
                return string.Equals(Value, obj.ToString(), icase);
            }
            else
            {
                return false;
            }
        }

        public int IndexOf(string Other)
        {
            return Other.IndexOf(Other, icase);
        }
        public bool Contains(string Other)
        {
            return IndexOf(Other) >= 0;
        }

        public override int GetHashCode()
        {
            if (Value == null)
                return 0;
            else
                return StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
        }

        public override string ToString()
        {
        return Value;
        }

        public int Compare(IString x, IString y)
        {
            return string.Compare(x.Value, y.Value, icase);
        }
        public int Compare(string x, string y)
        {
            return string.Compare(x, y, icase);
        }

        public int CompareTo(object obj)
        {
            if (obj is IString)
                return Compare(this, (IString)obj);
            else if (obj is string)
                return Compare(Value, (string)obj);
            else if (Value != null)
                return Value.CompareTo(obj);
            else
                return -1;
        }

        public int CompareTo(IString other)
        {
            return Compare(this, other);
        }

        public int CompareTo(string other)
        {
            return Compare(Value, other);
        }

        public static implicit operator string(IString From)
        {
            return From.Value;
        }
        public static implicit operator IString(string From)
        {
            return new IString(From);
        }

        #region IString to IString operators
        public static bool operator ==(IString Str1, IString Str2)
        {
            return string.Equals(Str1.Value, Str2.Value, icase);
        }
        public static bool operator !=(IString Str1, IString Str2)
        {
            return !string.Equals(Str1.Value, Str2.Value, icase);
        }
        public static IString operator +(IString Str1, IString Str2)
        {
            return (IString)(Str1.Value + Str2.Value);
        }
        public static bool operator >(IString Str1, IString Str2)
        {
            return Str1.CompareTo(Str2) > 0;
        }
        public static bool operator >=(IString Str1, IString Str2)
        {
            return Str1.CompareTo(Str2) >= 0;
        }
        public static bool operator <(IString Str1, IString Str2)
        {
            return Str1.CompareTo(Str2) < 0;
        }
        public static bool operator <=(IString Str1, IString Str2)
        {
            return Str1.CompareTo(Str2) <= 0;
        }
        #endregion IString to IString operators


        #region string to IString operators
        public static bool operator ==(string Str1, IString Str2)
        {
            return string.Equals(Str1, Str2.Value, icase);
        }
        public static bool operator !=(string Str1, IString Str2)
        {
            return !string.Equals(Str1, Str2.Value, icase);
        }
        public static IString operator +(string Str1, IString Str2)
        {
            return (IString)(Str1 + Str2.Value);
        }
        public static bool operator >(string Str1, IString Str2)
        {
            return Str2.CompareTo(Str1) < 0;
        }
        public static bool operator >=(string Str1, IString Str2)
        {
            return Str2.CompareTo(Str1) <= 0;
        }
        public static bool operator <(string Str1, IString Str2)
        {
            return Str2.CompareTo(Str1) > 0;
        }
        public static bool operator <=(string Str1, IString Str2)
        {
            return Str2.CompareTo(Str1) >= 0;
        }
        #endregion string to IString operators


        #region IString to string operators
        public static bool operator ==(IString Str1, string Str2)
        {
            return string.Equals(Str1.Value, Str2, icase);
        }
        public static bool operator !=(IString Str1, string Str2)
        {
            return !string.Equals(Str1.Value, Str2, icase);
        }
        public static IString operator +(IString Str1, string Str2)
        {
            return (IString)(Str1.Value + Str2);
        }
        public static bool operator >(IString Str1, string Str2)
        {
            return Str1.CompareTo(Str2) > 0;
        }
        public static bool operator >=(IString Str1, string Str2)
        {
            return Str1.CompareTo(Str2) >= 0;
        }
        public static bool operator <(IString Str1, string Str2)
        {
            return Str1.CompareTo(Str2) < 0;
        }
        public static bool operator <=(IString Str1, string Str2)
        {
            return Str1.CompareTo(Str2) <= 0;
        }
        #endregion IString to string operators

    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法让string.Equal(object)实际处理IString作为字符串?

SLa*_*aks 9

您不需要首先创建这样的类型.
相反,你应该使用这个StringComparer类.

例如:

var dict = new Dictionary<String, string>(StringComparer.OrdinalIgnoreCase);
dict["Help"] = "thanks!";
Assert.AreEqual("thanks!", dict["hELP"]);
Run Code Online (Sandbox Code Playgroud)

要么

List<String> list = new List<String>();
list.Add("help");
Assert.IsTrue(list.Contains("Help", StringComparer.OrdinalIgnoreCase));
Run Code Online (Sandbox Code Playgroud)

另请注意,不应该命名IString; 只有接口才能开始I.

要回答你的问题,不; 这不可能.