在泛型结构类型与可空结构类型之间使用==定义表达式时引发的奇怪异常
本文关键字:类型 结构 异常 表达式 泛型 之间 定义 | 更新日期: 2023-09-27 18:15:29
最终更新:看看这个新问题,它将问题缩小到泛型结构体。
我有一些代码正在构建一个Expression<Func<..>>
,将值类型与相同值类型的可空值进行比较。在定义表达式的行中,我得到以下InvalidOperationException
:
操作符"Equal"的操作数与方法"op_Equality"的形参不匹配。
对此有何解释?
注意:任何重写的方法都不会被调用,当。net构建表达式时抛出异常
下面是重现异常的完整代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace ConsoleApplication1
{
struct MyStruct<T> : IEquatable<MyStruct<T>>
where T : struct
{
private readonly T _value;
public MyStruct(T val) { this._value = val; }
public override bool Equals(object obj)
{
return false;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public static bool operator ==(MyStruct<T> a, MyStruct<T> b)
{
return false;
}
public static bool operator !=(MyStruct<T> a, MyStruct<T> b)
{
return false;
}
public bool Equals(MyStruct<T> other)
{
return false;
}
}
class Program
{
static void Main(string[] args)
{
Expression<Func<MyStruct<int>, Nullable<MyStruct<int>>, bool>> expr =
(value, nullableValue) => value == nullableValue;
Console.ReadLine();
}
}
}
Update:大大简化了重现异常的代码
还有:注意使用Func而不是表达式不会导致此异常:
Func<MyStruct<int>, Nullable<MyStruct<int>>, bool> func =
(value, nullableValue) => value == nullableValue;
func(new MyStruct<int>(), null);
上面的运行没有错误。
更新3:似乎删除IEquatable<>
接口并不能防止异常,所以代码可以进一步简化
编辑: 我将把这个答案留在这里,尽管问题有点改变,但可能对将来的人研究这个有帮助:
下面更正了使用Expression<Func<..>>
时的问题,但OP发现只使用Func<...>
就解决了这个问题。
你得到这个是因为你的operator==
正在为两个参数寻找MyStruct<T>
,但你正试图传递Nullable<MyStruct<T>>
。
您需要重写来处理Nullable<MyStruct<T>>
显然,这里发生的事情与泛型结构(在本例中为MyStruct<T>
)与非泛型结构之间的差异有关。如果我将结构体更改为以下更简单的非泛型类,则异常消失:
struct MyStruct
{
private readonly int _value;
public MyStruct(int val) { this._value = val; }
public override bool Equals(object obj) { return false; }
public override int GetHashCode() { return base.GetHashCode(); }
public static bool operator ==(MyStruct a, MyStruct b) { return false; }
public static bool operator !=(MyStruct a, MyStruct b) { return false; }
}
对于常规(非泛型)结构,. net满足于创建似乎向op_Equality方法(不接受空值)传递空值的表达式。
对于泛型结构,它会因为那个奇怪的异常而失败。
我仍然不知道为什么泛型和非泛型结构体之间有区别,所以我将在一个单独的问题中问这个