2

我有两个类都派生自同一个父类:

public class People{
    public string BetterFoot;

    public override bool Equals(object obj){
        if (obj == null || this.GetType() != obj.GetType())
            return false;
        People o = (People)obj;
        return (this.BetterFoot == o.BetterFoot);
    }

public class LeftiesOrRighties: People{
    public string BetterHand;

    public override bool Equals(object obj){
        if (obj == null || this.GetType() != obj.GetType())
            return false;
        LeftiesOrRighties o = (LeftiesOrRighties)obj;
        return (this.BetterFoot == o.BetterFoot) &&
        (this.BetterHand == o.BetterHand)
    }
}

public class Ambidextrous: People{
    public string FavoriteHand;
}

(那里也有 GetHashCodes,但我知道它们有效。)我想根据它们的根 Equals() 比较它们的集合:

ThoseOneHanded = new List<LeftiesOrRighties>(){new LeftiesOrRighties(){BetterFoot = "L"}};
ThoseTwoHanded = new List<Ambidextrous>(){new Ambidextrous(){BetterFoot = "L"}};
//using NUnit
Assert.That ((People)ThoseOneHanded[0], Is.EqualTo((People)ThoseTwoHanded[0])));

不幸的是,这会返回false

为什么?铸造不应该使它们(出于所有意图和目的,如果不完全是)相同的类型,从而使用基本方法吗?如果不是,我如何真正将底层类型转换回People?

4

2 回答 2

2

Cast 不会更改对象本身,因此 GetType 的结果将始终相同,因此您this.GetType() != obj.GetType()将是 true,因此该函数将返回 false。

以下逻辑可能会获得您想要的行为(并且您不需要强制转换为 People)

public class People 
{ 
    public string BetterFoot; 

    public override bool Equals(object obj)
    { 
        var o = obj as People;
        if (o == null) return false;
        return (this.BetterFoot = o.BetterFoot); 
} 

public class LeftiesOrRighties: People 
{ 
    public string BetterHand; 

    public override bool Equals(object obj) 
    { 
        var o = obj as LeftiesOrRighties; 
        if ( o == null) return base.Equals(obj);
        return (this.BetterFoot = o.BetterFoot) && (this.BetterHand = o.BetterHand) 
    } 
} 

public class Ambidextrous: People
{ 
    public string FavoriteHand; 
} 
于 2012-07-13T23:31:36.717 回答
0

As Bob Vale pointed out, the cast does not change type.

The standard solution used across the .NET Framework is to use custom object implementing IEqualityComparer or its generic variant. Then your compare/find method takes 2 objects/collections and uses comparer to perform the custom comparison.

I.e. many LINQ methods take custom compare to find/filter objects like Enumerable.Distinct

public static IEnumerable<TSource> Distinct<TSource>(
    this IEnumerable<TSource> source,
    IEqualityComparer<TSource> comparer
)

Sample comparer:

class Last3BitsComparer : IEqualityComparer<int>
{
    public bool Equals(int b1, int b2)
    {
        return (b1 & 3) == (b2 & 3);
    }
    public int GetHashCode(int bx)
    {
        return bx & 3;
    }
}
于 2012-07-14T00:01:51.360 回答