2010-11-17 97 views
2

我創建了一個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)實際處理IString作爲一個字符串?

+0

您應該使用'OrdinalIgnoreCase'而不是'InvariantCultureIgnoreCase';它更快,更安全。 – SLaks 2010-11-17 17:09:00

+0

另外,'返回StringComparer.OrdinalIgnoreCase.GetHashCode(Value);'。 – SLaks 2010-11-17 17:09:19

+0

除此之外,事實上它不是必需的,你的結構看起來不錯。 – SLaks 2010-11-17 17:10:03

回答

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開始。

要回答你的問題,不要;這不可能。

2

不,沒有。 String.Equals(object)方法嚴格依賴於所提供的String類型的值。它執行CLR類型檢查,不考慮任何用戶定義的轉換或函數,因此只能與System.String的實例一起使用

相關問題