当前位置: 首页 > 编程语言 > C#

为什么在构建将operator==提升为可为空的表达式时,对泛型和非泛型结构的处理方式不同?

时间:2023-04-10 20:42:46 C#

为什么在构建将operator==提升为可为空的表达式时,对泛型和非泛型结构的处理方式不同?这看起来像是将null提升为通用结构上的操作数的错误。考虑下面的伪结构,它覆盖了operator==:structMyStruct{privatereadonlyint_value;publicMyStruct(intval){this._value=val;}publicoverrideboolEquals(objectobj){returnfalse;}publicoverrideintGetHashCode(){returnbase.GetHashCode();}publicstaticbooloperator==(MyStructa,MyStructb){returnfalse;}publicstaticbooloperator!=(MyStructa,MyStructb){returnfalse;现在考虑以下表达式:ExpressionexprA=(valueA,valueB)=>valueA==valueB;表达式exprB=(nullableValueA,nullableValueB)=>nullableValueA==nullableValueB;表达式exprC=(nullableValueA,valueB)=>nullableValueA==valueB;所有三个都按预期编译和运行。当它们被编译时(使用.Compile()),它们产生以下代码(从IL翻译成英语):第一个只接受MyStruct(不可空)args的表达式,只调用op_Equality(我们的运算符==实现)第二个表达式在编译时生成检查每个参数以查看它是否为HasValue的代码。如果两者都不是(均等于null),则返回true。如果只有一个值,则返回false。否则,将对两个值调用op_Equality。第三个表达式检查可空参数以查看它是否有值-如果没有,则返回false。否则,调用op_Equality。到目前为止,一切都很好。下一步:对泛型类型执行完全相同的操作-在类型定义中将MyStruct更改为MyStruct,并将其更改为MyStruct。现在,第三个表达式编译但抛出运行时异常InvalidOperationException并显示以下消息:运算符“Equal”的操作数与方法“op_Equality”的参数不匹配。我希望通用结构的行为与非通用结构完全一样,具有上面提到的所有可为null的提升。所以我的问题是:为什么通用结构和非通用结构之间存在差异?这个异常是什么意思?这是C#/.NET中的错误吗?请参阅此要点以获取重现此内容的完整代码。简短的回答是:是的,这是一个错误。我在下面放了一个最小的复制和一个简短的分析。我很抱歉。我写了很多代码,所以这可能是我的错。我已将副本发送给Roslyn开发、测试和项目管理团队。我怀疑这在Roslyn中是否可重现,但他们会验证它是否不会,并查看这是否成为C#5服务包中的标准。如果您也希望在connect.microsoft.com上被跟踪,请随时在connect.microsoft.com上输入问题。最小复制:使用系统;使用System.Linq.Expressions;structS{publicstaticbooloperator==(Sa,Sb){返回假;}publicstaticbooloperator!=(Sa,Sb){返回假;}}classProgram{staticvoidMain(){Expression?,S,bool>>x=(a,b)=>a==b;在最小重现中,生成的代码等效于ParameterExpressionpa=Expression.Parameter(typeof(S?),"a");ParameterExpressionpb=Expression.Parameter(typeof(S),"b");Expression.Lambda?,S,bool>>(Expression.Equal(pa,pb,false,infoof(S.op_Equality)newParameterExpression[2]{pa,pb});其中infoof是获取MethodInfo的伪运算符给定方法的正确代码是:ParameterExpressionpa=Expression.Parameter(typeof(S?),"a");ParameterExpressionpb=Expression.Parameter(typeof(S),"b");Expression.Lambda?,S,bool>>(Expression.Equal(pa,Expression.Convert(pb,typeof(S?),false,infoof(S.op_Equality)newParameterExpression[2]{pa,pb});Equal方法不能处理一个nullable和non-nullable操作数。它要求两者都为空或两者都可以为空。(注意false是true。这个布尔值控制促进平等的结果是否是一个促进的布尔值;在C#中不是,在VB中是。)是的,这个错误在Roslyn(开发中的编译器)中消失了。我们将看到现有产品。以上为C#学习教程:构造将operator==提升为nullable的表达式时,为什么泛型和非泛型构造区别对待?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: