在泛型结构类型与可空结构类型之间使用==定义表达式时引发的奇怪异常

本文关键字:类型 结构 异常 表达式 泛型 之间 定义 | 更新日期: 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方法(不接受空值)传递空值的表达式。

对于泛型结构,它会因为那个奇怪的异常而失败。

我仍然不知道为什么泛型和非泛型结构体之间有区别,所以我将在一个单独的问题中问这个