假设我有这些物品
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();
}
}
答案 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));
建议使用泛型类型而不是使用字典中的对象;考虑将密钥从对象更改为类型。