Упрощенный из этого вопроса и избавлен от возможного воздействия 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();
}
}
"false" - результат оператора ceq
в CIL приведенного выше кода (подробности см. в исходном вопросе). Итак, мои вопросы:
(1) Почему ==
переводится в ceq
вместо call Delegate Equals
?
Здесь я не заботиться о (отмене) переноса между Delegate и Action. Наконец, при вычислении a == b
, a имеет тип Action
, а b - Делегат
. Из спецификации:
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 являются производными от общего базовый тип, то общие операторы-кандидаты встречаются только в комбинированном установить один раз.
• Если набор возможных пользовательских операторов не пусто, то это становится набором операторов-кандидатов для операция. В противном случае предопределенный бинарный оператор op реализации, включая их поднятые формы, становятся набором кандидаты операторов на операцию. Предопределенные реализации данного оператора указаны в описании оператора (С §7.8 по §7.12).
• Правила разрешения перегрузки в §7.5.3: применяется к набору операторов-кандидатов для выбора лучшего оператора относительно списка аргументов (x, y), и этот оператор становится результат процесса разрешения перегрузки. Если разрешение перегрузки не удается выбрать один лучший оператор, возникает ошибка времени привязки.
7.3.5 Кандидаты в определяемые пользователем операторы
Для данного типа T и оператора операции op (A), где op - это перегружаемый оператор, а A - список аргументов, набор возможных пользовательских операторов, предоставляемых T для оператора op (A) определяется следующим образом:
• Определить тип T0. Если T является типом, допускающим значение NULL, T0 является его базовым типом, в противном случае T0 равно T.
• Для всех объявлений оператора op в T0 и всех снятых формы таких операторов, если применим хотя бы один оператор (§7.5.3.1) относительно списка аргументов A, то набор Операторы-кандидаты состоят из всех таких применимых операторов в T0.
• В противном случае, если T0 является объектом, набор операторов-кандидатов пуст.
• В противном случае набор операторов-кандидатов, предоставленный T0, является набором операторов-кандидатов, предоставляемых прямым базовым классом T0, или эффективный базовый класс T0, если T0 является параметром типа.
Согласно спецификации, a и b имеют один и тот же базовый класс Delegate
, очевидно, здесь должно применяться правило оператора ==
, определенное в Delegate
( operator == по существу вызывает Delegate.Equals). Но теперь похоже, что список кандидатов определяемых пользователем операторов пуст и, наконец, применен Object ==
.
(2) Должен ли (подчиняться) код FCL спецификации языка C #? Если нет, то мой первый вопрос не имеет смысла, потому что что-то специально лечится. И затем мы можем ответить на все эти вопросы, используя «о, это особый подход в FCL, они могут делать то, что мы не можем. Спецификация предназначена для внешних программистов, не говорите глупостей».