Gotcha de conversão de grupo de método implícito (parte 2)
Simplificado deessa questã e se livrou do possível efeito do LinqPad (sem ofensas), um aplicativo simples de console como este:
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();
}
}
Os resultados "falsos" do operadorceq
no CIL do código acima (visite a pergunta original para obter detalhes). Então, minhas perguntas são:
(1) Por que==
está traduzindo paraceq
ao invés decall Delegate Equals
?
Aqui não me importo com a (des) quebra entre Delegado e Ação. Por fim, ao avaliara == b
, a é do tipoAction
enquanto b é aDelegate
. Das especificações:
.3.4 Resolução de sobrecarga do operador binário
Uma operação do formato x op y, em que op é um operador binário sobrecarregável, x é uma expressão do tipo X e y é uma expressão do tipo Y, é processada da seguinte forma:
• O conjunto de operadores candidatos definidos pelo usuário fornecidos por X e Y para o operador de operação op (x, y) é determinado. O conjunto consiste na união dos operadores candidatos fornecidos por X e dos operadores candidatos fornecidos por Y, cada um determinado de acordo com as regras do §7.3.5. Se X e Y forem do mesmo tipo, ou se X e Y forem derivados de um tipo de base comum, os operadores candidatos compartilhados ocorrerão apenas no conjunto combinado uma ve
• Se o conjunto de operadores candidatos definidos pelo usuário não estiver vazio, ele se tornará o conjunto de operadores candidatos à operação. Caso contrário, as implementações de operadores binários op predefinidas, incluindo suas formas levantadas, tornam-se o conjunto de operadores candidatos à operação. As implementações predefinidas de um determinado operador são especificadas na descrição do operador (§7.8 a §7.12
• As regras de resolução de sobrecarga de §7.5.3 são aplicadas ao conjunto de operadores candidatos para selecionar o melhor operador com relação à lista de argumentos (x, y), e esse operador se torna o resultado do processo de resolução de sobrecarga. Se a resolução de sobrecarga falhar na seleção de um único melhor operador, ocorrerá um erro no tempo de ligaçã
.3.5 Operadores definidos pelo usuário candidatos
Dado um tipo T e um operador de operação op (A), em que op é um operador sobrecarregável e A é uma lista de argumentos, o conjunto de operadores definidos pelo usuário candidatos fornecidos por T para o operador op (A) é determinado da seguinte forma:
• Determine o tipo T0. Se T é um tipo anulável, T0 é seu tipo subjacente, caso contrário, T0 é igual a T.
• Para todas as declarações de operação em T0 e todas as formas levantadas de tais operadores, se pelo menos um operador for aplicável (§7.5.3.1) com relação à lista de argumentos A, o conjunto de operadores candidatos consistirá em todos os operadores aplicáveis em T0.
• Caso contrário, se T0 for um objeto, o conjunto de operadores candidatos estará vazi
• Caso contrário, o conjunto de operadores candidatos fornecido por T0 é o conjunto de operadores candidatos fornecidos pela classe base direta de T0 ou pela classe base efetiva de T0 se T0 for um parâmetro de tipo.
Para as especificações, aeb têm a mesma classe baseDelegate
, obviamente a regra do operador==
definido emDelegate
deve ser aplicado aqui (o operador == invoca Delegate.Equals essencialmente). Mas agora parece que a lista de candidatos de operadores definidos pelo usuário está vazia e, finalmente,Object ==
é aplicado
(2) O código FCL deve obedecer às especificações da linguagem C #? Se não, minha primeira pergunta não tem sentido, porque algo é especialmente tratado. E então podemos responder a todas essas perguntas usando "oh, é um tratamento especial no FCL, eles podem fazer algo que não podemos. A especificação é para programadores externos, não seja bobo".