Почему общие и неуниверсальные структуры обрабатываются по-разному при построении выражения, которое поднимает оператор == до нуля?

Это похоже на ошибку при поднятии до нуля операндов на общих структурах.

Рассмотрим следующую фиктивную структуру, которая переопределяетoperator==:

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; }
}

Теперь рассмотрим следующие выражения:

Expression<Func<MyStruct, MyStruct, bool>> exprA   = 
    (valueA, valueB) => valueA == valueB;

Expression<Func<MyStruct?, MyStruct?, bool>> exprB = 
    (nullableValueA, nullableValueB) => nullableValueA == nullableValueB;

Expression<Func<MyStruct?, MyStruct, bool>> exprC  = 
    (nullableValueA, valueB) => nullableValueA == valueB;

Все три компилируются и запускаются, как и ожидалось.

Когда они скомпилированы (используя.Compile()) они производят следующий код (перефразированный на английский из IL):

Первое выражение, которое принимает толькоMyStruct (не обнуляемый) args, просто вызовop_Equality (наша реализацияoperator ==)

Второе выражение, когда скомпилировано, производит код, который проверяет каждый аргумент, чтобы увидеть, если онHasValue, Если оба не (оба равныnull), возвращаетtrue, Если только один имеет значение, возвращаетfalse, В противном случае звонкиop_Equality на двух значениях.

Третье выражение проверяет обнуляемый аргумент, чтобы увидеть, имеет ли оно значение - если нет, возвращает false. В противном случае звонкиop_Equality.

Все идет нормально.

Следующий шаг: сделать то же самое с универсальным типом - изменитьMyStruct вMyStruct<T> везде в определении типа, и измените его наMyStruct<int> в выражениях.

Теперь третье выражение компилируется, но выдает исключение времени выполненияInvalidOperationException со следующим сообщением:

Операнды для оператора «Равный» не соответствуют параметрам метода «op_Equality».

Я ожидал бы, что родовые структуры будут вести себя точно так же, как и неуниверсальные, со всеми отменяемыми значениями, описанными выше.

Итак, мои вопросы:

Почему существует разница между общими и неуниверсальными структурами?В чем смысл этого исключения?Это ошибка в C # /. NET?

Полный код для воспроизведения этогодоступно в этом суть.

Ответы на вопрос(2)

Ваш ответ на вопрос