在 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
这对您不起作用的原因是 InternalAlarm
是 IAlarm
类型而不是 MyAlarm
。如果将类型更改为 MyAlarm
,您将获得 true
而不是 false
.
的比较结果
这是因为 IAlarm
没有定义 operator==
(注意:这样的运算符是静态的)。
我正在尝试实现记录类型以减少比较的复杂性。但是我 运行 遇到了相互比较记录的问题。当属性彼此相等时,我希望记录是相等的,但在我的代码中情况并非如此..
我有一条名为 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
这对您不起作用的原因是 InternalAlarm
是 IAlarm
类型而不是 MyAlarm
。如果将类型更改为 MyAlarm
,您将获得 true
而不是 false
.
这是因为 IAlarm
没有定义 operator==
(注意:这样的运算符是静态的)。