代码之家  ›  专栏  ›  技术社区  ›  Bryce Wagner

不区分大小写的字符串与非字符串的比较

  •  2
  • Bryce Wagner  · 技术社区  · 14 年前

    我创建了一个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(对象)中很好地发挥作用:

    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)来实际处理作为string的IString?

    2 回复  |  直到 14 年前
        1
  •  9
  •   SLaks    14 年前

    您不需要首先创建这样的类型。
    相反,您应该使用 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 .

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

        2
  •  2
  •   JaredPar    14 年前

    不,没有。这个 String.Equals(object) 方法对提供的类型为的值具有硬依赖性 String . 它执行CLR类型检查,该检查不考虑任何用户定义的转换或函数,因此仅适用于 System.String