Сравнение строки без учета регистра без учета регистра - PullRequest
2 голосов
/ 17 ноября 2010

Я создал структуру 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 (объект), чтобы фактически иметь дело с IString как строкой?

Ответы [ 2 ]

9 голосов
/ 17 ноября 2010

Во-первых, вам не нужно создавать такой тип.
Вместо этого вы должны использовать класс 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 голосов
/ 17 ноября 2010

нет там нет.Метод String.Equals(object) имеет жесткую зависимость от предоставленного значения типа String.Он выполняет проверку типа CLR, которая не учитывает определенные пользователем преобразования или функции и, следовательно, будет работать только с экземпляром System.String

...