按值比较引用类型对象,无需手动覆盖 Equals 方法

问题描述 投票:0回答:1

这可能是一个初学者的问题,但我有一个问题,我找不到现有的解决方案,希望你能在这里帮助我。

我想按值比较引用类型对象的实例,而不手动覆盖此类及其子类中的

.Equals()
方法。这是因为我不想在类中编写所有代码,尤其是它有很多子代码,因为这会给已经庞大的代码库增加很多复杂性。有没有一种方法可以比较此类(或其子类)的两个对象,而不必为每个类编写实现?

记录不是一种选择,因为它们需要保持可变。 结构是不可能的,因为我仍然希望对象是引用类型,因为它们被传递了很多。

理想情况下,我也希望能够在某些情况下仅使用“值类型比较”,同时将“引用类型比较”保留为默认值。

有没有办法在 C# 中本地执行此操作,而无需为从相关类继承的每个类编写附加函数/覆盖

.Equals()
.GetHash()

我的代码看起来有点类似于:

using System;
namespace SubwaySystem{

public abstract class Passenger {
    public string name;
    public int identificationNumeber;
    public int age;
}

public class SingleTicketPassenger : Passenger
{
    public string ticketModel;
    public string ticketprice;
}

public class SubscriptionPassenger : Passenger
{
    public DateTime subscriptionExpiryDate; 
    public int subscriptionPrice;
    public string subscriptionModel;
}


public class GateHopper : Passenger
{
    public string entryStation;
    public string? arrestRecordID;
    public bool firstOffence;
}

// many more classes inherenting from Passenger

public class Subway {
    public Passenger oldestPassengerOnBoard;
    public string model;
    public string line;
    public DateTime constructionDate;
    public int speed;

    public override bool Equals(object? obj)
    {
        var otherSubway = obj as Subway;
        return this.Equals(otherSubway);
    }
    
    public bool Equals(Subway otherSubway)
    {
        return otherSubway != null &&
        otherSubway.oldestPassengerOnBoard == oldestPassengerOnBoard &&
        otherSubway.model == model &&
        otherSubway.line == line &&
        otherSubway.constructionDate == constructionDate &&
        otherSubway.speed == speed;
    }
    
    public override int GetHashCode()
    {
        unchecked 
        {
            int hash = 7;
            hash = hash * 11 + oldestPassengerOnBoard.GetHashCode();
            hash = hash * 11 + speed.GetHashCode();
            return hash;
        }        
    }
}
}

我想要做的是确保两个地铁不仅在最年长的乘客按引用相等时相等,而且按值相等。 (在实际的代码中,它更有意义,在这个例子中,只要与我保持一致,并假设两个人是同一个人,如果他们具有相同的属性)。乘客的哈希码当然也必须仅依赖于他们的属性。

最后我基本上会喜欢可变记录。或者类似于通用对象上的

.CompareByValue()
方法。

c# reference compare equality
1个回答
0
投票

按值比较对象时,有很多可能的边缘情况(您只比较属性吗?只比较字段?如果字段包含对象怎么办?),但如果您只想按公共字段进行比较,您可以编写一个为所有引用类型执行此操作的扩展方法。使用 Reflection 迭代字段并获取值,然后使用值类型的

Equals
方法,或者如果是引用类型,则递归调用
CompareByValue

static class ComparisonExtensions
{
    static public bool CompareByValue<T>(this T source, T other) where T : class
    {
        var fields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public);
        foreach (var field in fields)
        {
            var lhs = field.GetValue(source);
            var rhs = field.GetValue(other);
            var equal = field.FieldType.IsValueType ? !lhs.Equals(rhs): lhs.CompareByValue(rhs);
            if (!equal) return false;
        }
        return true;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.