1

カスタム文字列クラスを作成しています。string(主に自己啓発の目的で -拡張メソッドで簡単に実行できなかった通常のクラスよりも優れたものを考え出すつもりはないことを私は知っています。)私の単体テストでの平等。1つを除いて、ほぼすべての点で機能します。単体テストは次のとおりです。

MyString myStr = "MyNewString";
Assert.AreEqual("MyNewString", myStr); //Fails
Assert.AreEqual(myStr, "MyNewString");
Assert.IsTrue(myStr.Equals("MyNewString"));
Assert.IsTrue(("MyNewString").Equals(myStr));
Assert.IsTrue(myStr == "MyNewString");
Assert.IsTrue("MyNewString" == myStr);

string realString = "MyNewString";
Assert.AreEqual(realString, myStr); //Fails
Assert.AreEqual(myStr, realString);
Assert.IsTrue(myStr.Equals(realString));
Assert.IsTrue(realString.Equals(myStr));
Assert.IsTrue(myStr == realString);
Assert.IsTrue(realString == myStr);

失敗した場合はどちらも.ToString()afterを追加すると成功myStrしますが、他の場合は必要ありません。string暗黙の変換が設定されていても、のEqualsメソッドが私のクラスを認識していないためだと思います。クラスの関連部分は次のとおりです。

public struct MyString : ICloneable, IComparable<MyString>, IComparable<string>,
    IEnumerable<char>, IEquatable<MyString>, IEquatable<string>
{
    private char[] text;

    //Constructors
    ...

    public static implicit operator MyString(string s)
    {
        return s == null ? null : new MyString(s);
    }
    public static implicit operator string(MyString s) { return s.ToString(); }

    public static bool operator ==(MyString a, MyString b) { return a.Equals(b); }
    public static bool operator !=(MyString a, MyString b) { return !(a.Equals(b)); }
    public static bool operator ==(MyString a, string b) { return a.Equals(b); }
    public static bool operator !=(MyString a, string b) { return !(a.Equals(b)); }
    public static bool operator ==(string a, MyString b) { return b.Equals(a); }
    public static bool operator !=(string a, MyString b) { return !(b.Equals(a)); }

    public override string ToString() { return new string(text); }
    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;
        if (base.Equals(obj))
            return true;
        if (obj is MyString)
            return this.Equals((MyString)obj);
        if (obj is string)
            return this.Equals((string)obj);
        return false;
    }
    public bool Equals(MyString other) { return this.CompareTo(other) == 0; }
    public bool Equals(string other) { return this.CompareTo(other) == 0; }
}

と regularCompareTo()の両方にもがありますが、それらが機能することを信じてください。この平等テストを機能させるために他にできることはありますか? これは、他のすべてのケースで機能するようです。実際に内部でどのように動作するかはわかりませんが、同等性をテストする他のすべての方法が機能する場合、これが失敗するのはなぜですか?MyStringstringAssert.AreEqual

編集:関連する可能性があるため、私の GetHashCode() を追加します:

public override int GetHashCode()
{
    int hash = 0;
    for (int i = 0; i < Length; i++ )
        hash ^= (i * this[i]);
     return hash;
}

確かにこれはおそらく一致しませんstring.GetHashCode()が、コードが表示されないため、知る方法がありません。(メタデータは表示されますが、ヘッダーのみが含まれており、実装は含まれていません。)string.GetHashCode()次へのショートカットに置き換えてみました。

public override int GetHashCode()
{
    return new string(text).GetHashCode();
}

それでもうまくいきません。また、拡張メソッドを追加してみました:

public static bool Equals(this string a, MyString b) { return b.Equals(a); }

それもうまくいきませんでした。他のアイデアはありますか?

4

1 に答える 1

0

コール スタックには、どのオペレータも呼び出さない呼び出しがあるAssert.AreEqual(object, object) と想定されます。http://blogs.msdn.com/b/csharpfaq/archive/2004/03/29/when-should-i-use-and-when-should-i-use-equals.aspxobject.Equals(object, object)を参照 してください。上書き
GetHashCode()

少し延長する必要がありました。を呼び出し
Assert.AreEqual(a,b)ます。したがって、テストは を呼び出します。の実装は、ReferenceEqualsComparism の String への暗黙的なキャストを行います。そのため、文字列への暗黙的なキャストが存在しない限り、string.equality() は失敗します。要するに: MyString から string への暗黙的なキャストが機能しません => In c# 3.0, is it possible to add implicit operator to the string class? を参照してください。object.Equals(a,b)a.equals(b)string.Equals(b)string.Equals

  var myStr = "hello" as MyString;   // does call implicit cast to MyString
  var y = myStr as string;           // does not call implicit cast to String becaus you are not owner of string
于 2013-07-22T13:48:55.813 に答える