1

Final update: See this new question that narrows the problem down to generic structs.


I have some code that is building an Expression<Func<..>> that compares a value type to the nullable of the same value type. In the line that defines the expression, I'm getting the following InvalidOperationException:

The operands for operator 'Equal' do not match the parameters of method 'op_Equality'.

Any explanation for this?

Note: None of the overriden methods are ever called, the exception is thrown when the expression is being built by .NET

Here's the full code to reproduce the exception:

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: Greatly simplified the code that reproduces the exception


Also: Note that using a Func instead of an expression does not cause this exception:

Func<MyStruct<int>, Nullable<MyStruct<int>>, bool> func =
    (value, nullableValue) => value == nullableValue;

func(new MyStruct<int>(), null);

The above runs with no errors.


Update 3: Seems that removing the IEquatable<> interface doesn't prevent the exception, so the code can be further simplified.

4

2 回答 2

1

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 方法(不接受可空值)的表达式。

对于通用结构,它会因奇怪的异常而失败。

我仍然不知道为什么泛型和非泛型结构之间存在差异,所以我将在一个单独的问题中提出这个问题

于 2013-05-28T16:53:31.080 回答
1

编辑: 即使问题发生了变化,我也会将这个答案留在这里,但可能有助于未来的人们研究这个问题:

下面纠正了使用时的问题Expression<Func<..>>,但OP发现只是使用Func<...>解决了这个问题。


你得到这个是因为你operator==正在寻找MyStruct<T>这两个参数,但你试图传入Nullable<MyStruct<T>>.

您需要进行覆盖以处理Nullable<MyStruct<T>>

于 2013-05-24T18:41:53.473 回答