gpt4 book ai didi

c# - 为什么在实现隐式转换时 C# 记录会产生不同的 Linq 表达式?

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

我想了解为什么带有隐式转换的 C# 记录会生成意外的 Linq 表达式。

以下链接演示了当 Record 具有与 Class 或 Struct 相同的隐式转换实现时如何为 Record 生成不同的 Linq 表达式。

https://dotnetfiddle.net/LDJJct

这是在开发用于 Entity Framework 的自定义类型时发现的。 Entity Framework 抛出一个错误,指出当使用记录实现自定义类型时不支持表达式。使用类或结构时,表达式的行为符合预期。

这让我们发现根本问题似乎是生成的 .NET 表达式与记录实现不同。

使用 Record 或 Record 结构的表达式(意外):

System.Collections.Generic.List`1[TestObject].Where(x => (Convert(x.Id, Record) == value(Program+<>c__DisplayClass0_0)._record))

使用 Class 或 Struct 的表达式(预期):

System.Collections.Generic.List`1[TestObject].Where(x => (x.Id == Convert(value(Program+<>c__DisplayClass0_0)._class, Int32)))

Convert(x.Id, Record) 最终出乎意料, Entity Framework 默认不支持。我知道 EF ValueConverters 可以解决这个问题。但我想知道为什么这会产生不同的表达式。

有趣的是,如果您注释掉 Record 上的操作符之一,那么您将获得带有 Record 的预期 Linq 表达式!

更新 - 为了澄清,我特别感兴趣的是 Records 是否可以被强制生成一个 Expression,它更类似于为 Class 和 Struct 示例生成的表达式。大多数情况下,我想首先了解为什么 Records 会出现这种意外行为。

最佳答案

来自language reference ;

If the set of candidate user-defined operators is not empty, then this becomes the set of candidate operators for the operation. Otherwise, the predefined binary operator «op» implementations, including their lifted forms, become the set of candidate operators for the operation.

换句话说,因为 C# 编译器为所有记录类型定义了“用户定义的”== 运算符。并且因为您有一个来自 int 的隐式转换,所以这个运算符是一个候选者。

所以“预定义的”bool operator ==(int x, int y) 根本不被考虑,即使 record 参数具有到该类型的隐式转换。

您可以定义更多“用户定义的”相等运算符,删除您的 record(int) 隐式转换,或者在每个表达式中添加显式转换。

关于c# - 为什么在实现隐式转换时 C# 记录会产生不同的 Linq 表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73859882/

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