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

时间:2010-11-17 17:02:43

标签: c# string equals case-insensitive

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

List<IString> list = new List<IString>();
list.Add("help");
Assert.IsTrue(list.Contains("Help"));

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

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

IString A1 = "A";
string A2 = "a";
Assert.AreEqual(A1, A2, "This passes");
Assert.AreEqual(A2, A1, "This fails");

以下是代码:

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

    }
}

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

2 个答案:

答案 0 :(得分:9)

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

例如:

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

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

另请注意,不应将其命名为IString;只有接口应以I开头。

回答你的问题,不;那是不可能的。

答案 1 :(得分:2)

不,没有。 String.Equals(object)方法对提供的值String类型具有很强的依赖性。它执行CLR类型检查,不检查任何用户定义的转换或函数,因此只能使用System.String的实例