gpt4 book ai didi

c# - C# 9 记录的自定义相等检查

转载 作者:行者123 更新时间:2023-12-02 11:16:11 26 4
gpt4 key购买 nike

据我了解,记录实际上是类,它们以您的对象是值驱动而不是引用驱动的方式实现自己的相等性检查。
总之,对于record Foo实现方式如下:var foo = new Foo { Value = "foo" }var bar = new Foo { Value = "foo" } , foo == bar表达式将导致 True ,即使他们有不同的引用( ReferenceEquals(foo, bar) // False )。
现在有了记录,即使在 the article发布在 .Net 博客上,它说:

If you don’t like the default field-by-field comparison behaviour ofthe generated Equals override, you can write your own instead.


当我尝试放置 public override bool Equals 时, 或 public override int GetHashCode , 或 public static bool operator == ,等等。我收到了 Member with the same signature is already declared错误,所以我认为这是一种受限制的行为, struct 并非如此。对象。
Failing example :
public sealed record SimpleVo
: IEquatable<SimpleVo>
{
public bool Equals(SimpleVo other) =>
throw new System.NotImplementedException();

public override bool Equals(object obj) =>
obj is SimpleVo other && Equals(other);

public override int GetHashCode() =>
throw new System.NotImplementedException();

public static bool operator ==(SimpleVo left, SimpleVo right) =>
left.Equals(right);

public static bool operator !=(SimpleVo left, SimpleVo right) =>
!left.Equals(right);
}
编译结果:
SimpleVo.cs(11,30): error CS0111: Type 'SimpleVo' already defines a member called 'Equals' with the same parameter types

SimpleVo.cs(17,37): error CS0111: Type 'SimpleVo' already defines a member called 'op_Equality' with the same parameter types

SimpleVo.cs(20,37): error CS0111: Type 'SimpleVo' already defines a member called 'op_Inequality' with the same parameter types
我的主要问题是,如果我们想自定义平等检查器的工作方式怎么办?我的意思是,我确实明白这违背了记录的全部目的,但另一方面,平等检查器并不是使记录使用起来很酷的唯一功能。
有人想要覆盖记录相等性的一个用例是因为您可能有一个 attribute这将从相等性检查中排除属性。以 this为例 ValueObject执行。
那么如果你扩展这个 ValueObject像这样的抽象类:
public sealed class FullNameVo : ValueObject
{
public FullNameVo(string name, string surname)
{
Name = name;
Surname = surname;
}

[IgnoreMember]
public string Name { get; }

public string Surname { get; }

[IgnoreMember]
public string FullName => $"{Name} {Surname}";
}
那么你会得到以下 results :
var user1 = new FullNameVo("John", "Doe");
var user2 = new FullNameVo("John", "Doe");
var user3 = new FullNameVo("Jane", "Doe");

Console.WriteLine(user1 == user2); // True
Console.WriteLine(ReferenceEquals(user1, user2)); // False
Console.WriteLine(user1 == user3); // True
Console.WriteLine(user1.Equals(user3)); // True
到目前为止,为了以某种方式实现上述用例,我已经实现了 an abstract record object并像这样使用它:
public sealed record FullNameVo : ValueObject
{
[IgnoreMember]
public string Name;

public string Surname;

[IgnoreMember]
public string FullName => $"{Name} {Surname}";
}
结果如下所示:
var user1 = new FullNameVo
{
Name = "John",
Surname = "Doe"
};

var user2 = new FullNameVo
{
Name = "John",
Surname = "Doe"
};

var user3 = user1 with { Name = "Jane" };

Console.WriteLine(user1 == user2); // True
Console.WriteLine(ReferenceEquals(user1, user2)); // False
Console.WriteLine(user1 == user3); // False
Console.WriteLine(user1.Equals(user3)); // False
Console.WriteLine(ValueObject.EqualityComparer.Equals(user1, user3)); // True
总而言之,我有点困惑,限制记录对象的相等方法的覆盖是预期行为还是因为它仍处于预览阶段?如果是设计使然,您会以不同(更好)的方式实现上述行为,还是继续使用类? dotnet --version输出: 5.0.100-rc.1.20452.10

最佳答案

the C#9 record proposal ,以下应该编译,即使在没有实际实现的情况下不是很有用..

// No explicit IEquatable<R> - this is synthesized!
public sealed record SimpleVo
{
// Not virtual, as SimpleVo (R) is sealed.
// Accepts SimpleVo? (R?), and not SimpleVo (R), as argument.
public bool Equals(SimpleVo? other) =>
throw new System.NotImplementedException();

// Optional: warning generated if not supplied when Equals(R?) is user-defined.
public int GetHashCode() =>
throw new System.NotImplementedException();

// No other “standard” equality members!
}
由于大部分代码都是合成的,因此对与等式相关的成员有限制。该提案包括预期合成基础类型的示例。
也就是说,给定 只是 Equals(R?)编译器创建一个 == , != , 和 Equals(object) .
可以通过在提案中搜索“用户定义”来找到可以定义的方法。
尝试覆盖/定义其他相等方法或运算符预计会失败:

It is an error if the override is declared explicitly.


该行为在“平等成员”中进行了讨论,并在以下段落中进行了总结:

The record type implements System.IEquatable<R> and includes a synthesized strongly-typed overload of book Equals(R? other) where R is the record type. The method is public, and the method is virtual unless the record type is sealed. The [Equals(R?)] method can be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or the explicit declaration doesn't allow overriding it in a derived type and the record type is not sealed.If Equals(R? other) is user-defined (not synthesized) but GetHashCode is not [user-defined], a warning is produced.

关于c# - C# 9 记录的自定义相等检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64326511/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com