与 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;
    }
}

与 C# 中的对象进行比较

是的,您应该重写 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>继承,然后覆盖EqualsGetHashCode,因为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> 来缩短代码。

如果泛型列表中的类型实现 IEquatableList<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