Неявный метод группового преобразования Гоча (часть 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, они могут сделать то, что мы не можем. Спецификация для сторонних программистов, не будь глупой».