在 C# 中比较记录类型与 LINQ

Comparing record types with LINQ in C#

我正在尝试实现记录类型以减少比较的复杂性。但是我 运行 遇到了相互比较记录的问题。当属性彼此相等时,我希望记录是相等的,但在我的代码中情况并非如此..

我有一条名为 MyAlarm 的记录 class,其中包含一些属性。它继承自空接口IAlarm

public record MyAlarm : IAlarm
{
    public int Prop1 { get; init; }
    public int Prop2 { get; init; }
}

一个名为 VisibleAlarm 的 class 具有 属性 的 IAlarm 加上一些额外的数据。

public record VisibleAlarm
{
    public IAlarm InternalAlarm { get; init; }
    public string Message { get; set; }
}

在名为 AlarmService 的 class 中,列出了 VisibleAlarms 并在需要时更新。此服务有一个可见警报列表。

此外,在此警报服务中,根据 IAlarm 属性 检查列表是否已存在警报。我试过两种方法:

public class AlarmService
{
    private List<VisibleAlarm> _alarms = new();

    // ... Other code that handles alarm stuff

    private VisibleAlarm GetExistingAlarm1(IAlarm alarm)
    {
        return _alarms.FirstOrDefault(a => a.InternalAlarm == alarm);
    }

    private VisibleAlarm GetExistingAlarm2(IAlarm alarm)
    {
        foreach (var existingAlarm in _alarms)
        {
            if (existingAlarm.InternalAlarm == alarm)
            {
                return existingAlarm;
            }
        }
    }
}

调试代码时,我看到 existingAlarm.InternalAlarm 的记录属性和给定的警报匹配,但 GetExistingAlarm 方法 return 仍然是错误的。由于接口 IAlarm,我是否遗漏了什么或必须实施 IEqualityComparer?

干杯

在你的代码行中:

return _alarms.FirstOrDefault(a => a.InternalAlarm == alarm);

a.InternalAlarm == alarm 正在调用 operator== 而不是 object.Equals() 来进行比较。

您可以通过将代码更改为:

来解决此问题
return _alarms.FirstOrDefault(a => a.InternalAlarm.Equals(alarm));

下面的程序演示了区别:

using System;

static class Program
{
    public static void Main()
    {
        MyAlarm ma1 = new MyAlarm { Prop1 = 1, Prop2 = 2 };
        MyAlarm ma2 = new MyAlarm { Prop1 = 1, Prop2 = 2 };
        
        VisibleAlarm va1 = new VisibleAlarm { InternalAlarm = ma1, Message = "message" };
        VisibleAlarm va2 = new VisibleAlarm { InternalAlarm = ma2, Message = "message" };

        Console.WriteLine(ma1 == ma2); // True
        Console.WriteLine(va1 == va2); // True
        Console.WriteLine(va1.InternalAlarm == va2.InternalAlarm); // False
        Console.WriteLine(va1.InternalAlarm.Equals(va2.InternalAlarm)); // True
    }

    public interface IAlarm
    {
        int Prop1 { get; }
        int Prop2 { get; }
    }

    public record MyAlarm : IAlarm
    {
        public int Prop1 { get; init; }
        public int Prop2 { get; init; }
    }

    public record VisibleAlarm
    {
        public IAlarm InternalAlarm { get; init; }
        public string Message       { get; set; }
    }
}

输出:

True
True
False
True

这对您不起作用的原因是 InternalAlarmIAlarm 类型而不是 MyAlarm。如果将类型更改为 MyAlarm,您将获得 true 而不是 false.

的比较结果

这是因为 IAlarm 没有定义 operator==(注意:这样的运算符是静态的)。