2012-08-24 13 views
11

tengo clase base Amétodos ¿Por qué sobrecargados tienen menor prioridad que método de instancia

public class A 
{ 
    public virtual void Method(A parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
    public virtual void Method(B parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
} 

Inhereted B

public class B : A 
{ 
    public virtual void Method(object parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 

    public override void Method(A parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 

    public override void Method(B parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
} 

clase estática S con método de extensión

public static class S 
{ 
    public static void Method(this B instance, B parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
} 

Ejemplo que crear instancia del tipo B e invocar Method en él, esperamos que sea public override void Method(B parameter) el resultado real es public virtual void Method(object parameter).

var b = new B(); 
b.Method(new B()); // B.Method (Object parameter) Why??? 

¿Por qué el compilador no selecciona el método más adecuado ??? UPD ¿Y por qué no es el método de extensión?

+3

'B' no está anidado pero se hereda. –

+0

@Henk Holterman gracias – user854301

+0

método de extensión no se llama si el objeto tiene un método con el mismo nombre. esto es para evitar romper el código antiguo donde la expectativa es llamar al método anterior y no a la extensión nueva. – Ankush

Respuesta

10

¿Por qué el compilador no selecciona el método más adecuado?

Debido a que es seguir las reglas de la especificación del lenguaje, en donde cualquiera de los métodos candidatos declaradas originalmente en una clase base (más si es que se hayan omitido en una clase derivada) se ignoran cuando la búsqueda de un método propuesto, a menos que el La clase derivada no tiene ningún método aplicable, en cuyo momento la búsqueda pasa a la clase base, etc.

Esto es designed to avoid the "brittle base class" problem, pero me parece difícil de asimilar en vista del método que se reemplaza en el derivado clase.

El bit correspondiente de la especificación de C# 4 es 7,4, que termina con esto:

Para búsquedas miembros en tipos distintos de parámetros de tipo e interfaces, y las búsquedas de miembros en las interfaces que son estrictamente de una sola herencia (cada interfaz en la cadena de herencia tiene exactamente cero o una interfaz base directa), el efecto de las reglas de búsqueda es simplemente que los miembros derivados esconden miembros base con el mismo nombre o firma.

EDIT: Acerca de los métodos de extensión ...

Y por qué no es el método de extensión?

Desde la sección 7.6.5.2 de la especificación:

En una invocación de método (§7.5.5.1) de una de las formas

expr . identifier () 
expr . identifier (args) 
expr . identifier <typeargs> () 
expr . identifier <typeargs> (args) 

si el procesamiento normal de la invocación no encuentra métodos aplicables, se intenta procesar el constructo como una invocación al método de extensión

Así que una el método de extensión es solo usado como último recurso, básicamente.

+0

Creo que la pregunta es por qué el código llama al método heredado, en lugar del método de extensión, pero es difícil de decir. – podiluska

+0

@podiluska: Creo que el método de extensión es una pista falsa. El OP no parece esperar que se llame ... –

+0

También es interesante por qué los métodos de extensión no se llaman también. – user854301

Cuestiones relacionadas