gpt4 book ai didi

c# - 从 C# 使用时 F# 记录类型的相等性

转载 作者:行者123 更新时间:2023-12-04 01:33:48 25 4
gpt4 key购买 nike

我在 F# 库中有以下记录类型:

type Rating = {
Id : string
AverageRating : decimal
ValueRange : int
Label : string }

正如预期的那样,以下测试在 F# 测试库中通过:

[Fact]
let ``ShouldConsiderTwoInstancesOfAClassToBeTheSame`` () =

let a = {Rating.Id = "id"
AverageRating = 4.3m
ValueRange = 10
Label = "label"}

let b = {Rating.Id = "id"
AverageRating = 4.3m
ValueRange = 10
Label = "label"}

a = b |> should equal true
a.Equals b |> should equal true
a <> b |> should equal false
System.Object.ReferenceEquals(a, b) |> should equal false

但是,C# 中的以下测试失败了……前两个断言都失败了,尽管第三个断言通过了:

    [Test]
public void ShouldConsiderTwoInstancesOfAClassToBeTheSame()
{
var a = new Rating("id", 4.3m, 10, "label");
var b = new Rating("id", 4.3m, 10, "label");

Assert.True(a == b);
Assert.False(a != b);
Assert.True(a.Equals(b));
Assert.False(ReferenceEquals(a, b));
}

在仅使用运算符从 C# 中使用时,是否有一种方法可以立即获得记录类型提供的结构相等性,或者您是否需要调用 Equals()?

最佳答案

在惯用的 C# 中,引用类型不应测试结构相等性。 IEquatable 作为契约(Contract)在语义上更有意义。

默认情况下,相等意味着引用相等。 F# 在这方面非常不同 - 它使用结构相等 进行比较。如果您查看 F# 为 a = b 做了什么,它会调用

a.Equals(b, GenericEqualityComparer);

但是,对于实现了 == 运算符的类型,C# 编译器知道选择运算符的方法。

push.0 //ldloc, ldfld, etc.
push.1
call bool Rating::op_Equality(valuetype Rating, valuetype Rating)

a == b 通常发生的情况是:

push.0
push.1
ceq

ceq比任何方法调用替代方法都快得多,并且是默认的相等比较,它为您提供相等的引用。

其他核心 .NET 类型可能未显式实现 ==!=,但 JIT 具有特定的实现细节来对这些内部类型(有符号的, fp 等),因此它们仍然正确等同。

如果 == 比较在语义上对您很重要,您可以自己实现运算符:

type Rating = {
Id : string
AverageRating : decimal
ValueRange : int
Label : string
} with
static member op_Equality (a: Rating, b: Rating) =
a.Equals b
static member op_Inequality (a: Rating, b: Rating) =
not (a.Equals b)

并且您的测试应该再次运行。

关于c# - 从 C# 使用时 F# 记录类型的相等性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60296763/

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