Неявный метод группового преобразования Гоча (часть 2)

Упрощенный отэтот вопрос и избавился от возможного аффекта от LinqPad (без оскорблений), простого консольного приложения, подобного этому:

public class Program
{
    static void M() { }    
    static void Main(string[] args)
    {
        Action a = new Action(M);
        Delegate b = new Action(M);
        Console.WriteLine(a == b);      //got False here
        Console.Read();
    }        
}

«Ложные» результаты от оператораceq в CIL кода выше (подробности см. в оригинальном вопросе). Итак, мои вопросы:

(1) Почему== переводит наceq вместоcall Delegate Equals?

Здесь меня не волнует (не) перенос между делегатом и действием. В самом последнем, при оценкеa == b, имеет типAction в то время как бDelegate, Из спецификации:

7.3.4 Разрешение перегрузки бинарного оператора

Операция вида x op y, где op - это перегружаемый двоичный оператор, x - это выражение типа X и y - выражение типа Y, обрабатывается следующим образом:

• Определен набор пользовательских операторов-кандидатов, предоставляемых X и Y для операционного оператора op (x, y). Набор состоит из объединения операторов-кандидатов, предоставленных X, и операторов-кандидатов, предоставленных Y, каждый из которых определяется по правилам §7.3.5. Если X и Y относятся к одному и тому же типу или если X и Y получены из общего базового типа, то операторы-кандидаты совместно используются в объединенном наборе только один раз.

• Если набор пользовательских операторов-кандидатов не пуст, тогда он становится набором операторов-кандидатов для операции. В противном случае предопределенные реализации бинарных операторов, включая их поднятые формы, становятся набором операторов-кандидатов для операции. Предопределенные реализации данного оператора указываются в описании оператора (§7.8–7.12).

• Правила разрешения перегрузки согласно §7.5.3 применяются к набору операторов-кандидатов для выбора лучшего оператора относительно списка аргументов (x, y), и этот оператор становится результатом процесса разрешения перегрузки. Если при разрешении перегрузки не удается выбрать лучший оператор, возникает ошибка времени привязки.

7.3.5. Пользовательские операторы-кандидаты.

Учитывая тип T и оператор операции op (A), где op - это перегружаемый оператор, а A - список аргументов, набор возможных пользовательских операторов, предоставляемых T для оператора op (A), определяется следующим образом:

• Определить тип T0. Если T является обнуляемым типом, T0 является его базовым типом, в противном случае T0 равен T.

• Для всех объявлений операторов в T0 и всех поднятых форм таких операторов, если хотя бы один оператор применим (§7.5.3.1) в отношении списка аргументов A, тогда набор операторов-кандидатов состоит из всех таких применимых операторов в T0.

• В противном случае, если T0 является объектом, набор операторов-кандидатов будет пустым.

• В противном случае набор операторов-кандидатов, предоставляемых T0, является набором операторов-кандидатов, предоставляемых прямым базовым классом T0, или эффективным базовым классом T0, если T0 является параметром типа.

Из спецификации А и В имеют одинаковый базовый классDelegateочевидно операторное правило== определяется вDelegate следует применять здесь (оператор == вызывает Delegate.Equals по существу). Но теперь похоже, что список кандидатов пользовательских операторов пуст и наконецObject == применены.

(2) Должен ли код FCL соответствовать спецификации языка C #? Если нет, мой первый вопрос не имеет смысла, потому что что-то специально рассматривается. И затем мы можем ответить на все эти вопросы, используя «о, это особый подход в FCL, они могут сделать то, что мы не можем. Спецификация для сторонних программистов, не будь глупой».

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

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