两个对象之间的字典比较

时间:2017-07-07 04:37:03

标签: c# asp.net dictionary

假设我有这些物品

    var address = new Address("5455 Apache Trail", "Queen Creek", "AZ", "85243");
    var person = new Person("Jane", "Smith", address);

我想通过使用字典来检查这些对象的相等性,所以它很像这样

    var dictionary = new Dictionary<object>{ [address] = address, [person] = person};
    Assert.IsTrue(dictionary.ContainsKey(new Address("5455 Apache Trail", "Queen Creek", "AZ", "85243")));
    Assert.IsTrue(dictionary.ContainsKey(new Person("Jane", "Smith", address)));

但是,它总是返回False。我在这里失踪了什么?

修改

添加自定义词典

public class Dictionary<T> : Dictionary<T, T> where T : class, new()
{
}

添加课程

public abstract class BaseModel
{
    public string Id { get; set; }

    public BaseModel()
    {
    }
}

public class Address : BaseModel
{
    public string Street { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }

    public Address() { }

    public override bool Equals(object value)
    {
        if (value == null)
            return false;

        Address mod = value as Address;

        return (mod != null)
            && (Street == mod.Street)
            && (City == mod.City)
            && (PostalCode == mod.PostalCode)
            && (State == mod.State);
    }

    public override int GetHashCode(){
        return base.GetHashCode();
    }

    public Address(string street, string city, string state, string postalCode) {
        this.Street = street;
        this.City = city;
        this.State = state;
        this.PostalCode = postalCode;
    }
}

public class Person : BaseModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Address Address { get; set; }

    public Person() { }

    public Person(string firstName, string lastName, Address address)
    {
        this.FirstName = firstName;
        this.LastName = lastName;
        this.Address = address;
    }

    public override bool Equals(object value)
    {
        if (value == null)
            return false;

        Person mod = value as Person;

        return (mod != null)
            && (FirstName == mod.FirstName)
            && (LastName == mod.LastName)
            && (Address.Equals(mod.Address));
    }


    public override int GetHashCode(){
        return base.GetHashCode();
    }
}

2 个答案:

答案 0 :(得分:2)

您需要传递相应IEqualityComparer的实例。 如果您没有传递任何比较器字典将使用默认比较器。 (EqualityComparer.Default)。如果传递的参数是对象的同一实例,则仅返回true。您将不得不创建自己的比较器

或者,您可以在要存储在字典中的所有类中覆盖GetHashCode和Equals。然后EqualityComparer.Default调用 GetHashCode Equals 的相应覆盖,然后设置。如果要覆盖这两个函数,则不需要创建比较器或将比较器传递给字典。

根据OP编辑进行编辑:

请注意, GetHashCode 的实施应与等于的实施保持一致:

a.Equals(b)=&gt; b.Equals(a)=&gt; a.GetHashCode()== b.GetHashCode()

在您的情况下,由于您仍在使用对象默认的GetHashCode,因此上述条件不成立。

GetHashCode应该像:

一样实现
  public override int GetHashCode(){
        return this.FirstName.GetHashCode() ^ 
               this.LastName.GetHashCode() ^ 
               this.Address.GetHashCode(); 
    }

答案 1 :(得分:1)

因为您创建了Address和Person的新引用,所以它不会与键匹配,以下Assert语句将起作用:

 var dictionary = new Dictionary<object, object> { [address] = address, [person] = person };
 Assert.IsTrue(dictionary.ContainsKey(address));
 Assert.IsTrue(dictionary.ContainsKey(person));

<强>更新

如果需要创建新引用,请为字典使用EqualityComparer参数:

public class CustomEqualityComparer : IEqualityComparer<object>
{
    public new bool Equals(object x, object y)
    {
        if (x is Address && y is Address)
        {
            var xAddress = x as Address;
            var yAddress = y as Address;
            return xAddress.Line1 == yAddress.Line1 &&
               xAddress.Line2 == yAddress.Line2 &&
               xAddress.Line3 == yAddress.Line3 &&
               xAddress.Line4 == yAddress.Line4;
        }

        if (x is Person && y is Person)
        {
            var xPerson = x as Person;
            var yPerson = y as Person;
            return xPerson.FirstName == yPerson.FirstName &&
               xPerson.LastName == yPerson.LastName;
        }

        return false;
    }

    public int GetHashCode(object obj)
    {
        if (obj is Address)
        {
            var address = obj as Address;
            return  address.Line1.GetHashCode() ^
                    address.Line2.GetHashCode() ^
                    address.Line3.GetHashCode() ^
                    address.Line4.GetHashCode();
        }

        if (obj is Person)
        {
            var person = obj as Person;
            return person.FirstName.GetHashCode() ^
                   person.LastName.GetHashCode();
        }

        return obj.GetHashCode();
    }
}

然后在你的测试中:

var dictionary = new Dictionary<object, object>(new CustomEqualityComparer())
        { [address] = address, [person] = person };
        Assert.IsTrue(dictionary.ContainsKey(new Address("5455 Apache Trail", "Queen Creek", "AZ", "85243")));
        Assert.IsTrue(dictionary.ContainsKey(person));

建议使用泛型类型而不是使用字典中的对象;考虑将密钥从对象更改为类型。