与 C# 中的对象进行比较
本文关键字:比较 对象 | 更新日期: 2023-09-27 18:30:22
你好,我是C#的新手,我有一个小问题:当我调用该方法时list1.contains(product)
它是否像 java 一样我们需要覆盖 Equals 方法?
如果是,这是这样做的方法吗?
public partial class product
{
public product()
{
}
public int idProduct { get; set; }
public override bool Equals(object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (this.GetType() != obj.GetType())
{
return false;
}
product other = (product)obj;
if (idProduct != other.idProduct)
{
return false;
}
return true;
}
}
是的,您应该重写 Equals 以为您的类提供相等语义。默认情况下,引用相等性将发挥作用。
您的 Equals 方法将起作用,但在 C# 中,我们也可以重写 == 运算符。因此,在 Equals 方法中使用可能不安全。最好使用 ReferenceEquals
进行参考比较:
public override bool Equals(object obj)
{
if (ReferenceEquals(obj,null))
{
return false;
}
if (ReferenceEquals(this,obj))
{
return true;
}
if (this.GetType() != obj.GetType())
{
return false;
}
product other = (product)obj;
if (idProduct != other.idProduct)
{
return false;
}
return true;
}
除了@driis答案之外,您还可以创建一个新的IEqualityComparer<Product>
,如下所示:
public sealed class ProductEqualityComparer : IEqualityComparer<Product>
{
public bool Equals(Product x, Product y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(x, null)) return false;
if (ReferenceEquals(y, null)) return false;
if (x.GetType() != y.GetType()) return false;
return x.idProduct == y.idProduct;
}
public int GetHashCode(Product obj)
{
return obj.idProduct;
}
}
然后,您可以将该Comparer
传递给Contains
,如下所示:
if (list1.Contains(product, new ProductEqualityComparer()))
{
}
其中list1
List<Product>
定义为:
Product product = new Product { idProduct = 1 };
List<Product> list1 = new List<Product>
{
new Product{idProduct = 1},
new Product{idProduct = 2}
};
或者,您可以从EqualityComparer<T>
继承,然后覆盖Equals
和GetHashCode
,因为MSDN声明
建议从
EqualityComparer<T>
类派生 而不是实现IEqualityComparer<T>
接口,因为EqualityComparer<T>
类使用IEquatable<T>.Equals
方法,而不是 Object.Equals 方法。 这与 Contains、IndexOf、LastIndexOf 和 Remove 一致Dictionary<TKey, TValue>
类和其他泛型的方法 收集。
public sealed class ProductEqualityComparer : EqualityComparer<Product>
{
public override bool Equals(Product x, Product y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(x, null)) return false;
if (ReferenceEquals(y, null)) return false;
if (x.GetType() != y.GetType()) return false;
return x.idProduct == y.idProduct;
}
public override int GetHashCode(Product obj)
{
return obj.idProduct;
}
}
可能值得一提的是,您可以通过实现 IEquatable<T>
来缩短代码。
如果泛型列表中的类型实现 IEquatable
,List<T>.Contains
将调用 IEquatable<T>.Equals
,避免强制转换:
public class product : IEquatable<product>
{
public int idProduct { get; set; }
// List<product>.Contains will call IEquatable<product>.Equals if available.
public bool Equals(product other)
{
return ReferenceEquals(other, this) || other.idProduct == this.idProduct;
}
// Note: you should still override object.Equals.
public override bool Equals(object other)
{
return this.Equals(other as product);
}
}
同样在 C# 类中通常是PascalCased
而不是camelCased
。