2011-09-22 22 views
12

Estoy un poco confundido acerca de cómo funcionan los métodos de extensión.C# Método de extensión anterior

Si estoy leyendo esto correctamente http://msdn.microsoft.com/en-us/library/bb383977.aspx y este If an extension method has the same signature as a method in the sealed class, what is the call precedence?.

Luego, lo siguiente debe escribir "Instancia", pero en su lugar escribe "Método de extensión".

interface IFoo 
{ 
} 

class Foo : IFoo 
{ 
    public void Say() 
    { 
     Console.WriteLine("Instance"); 
    } 
} 

static class FooExts 
{ 
    public static void Say(this IFoo foo) 
    { 
     Console.WriteLine("Extension method"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     IFoo foo = new Foo(); 
     foo.Say(); 
    } 
} 

Apreciamos cualquier ayuda para aclarar el comportamiento.

+0

¿Está seguro de anular un método incorporado con un método de extensión compilado? – kenny

+0

En un segundo vistazo o compilándolo, la interfaz no tiene Say(), entonces lo que tiene llama al método de extensión. Con Save() en la interfaz el compilador se queja con 'C: \ projects \ _play \ ExtensionMethods \ Program.cs (2,1): error CS0116: un espacio de nombre no puede contener directamente miembros como campos o métodos' – kenny

Respuesta

14

La gran diferencia aquí es que ha definido un método de extensión para la interfaz IFoo, y su variable foo es del tipo IFoo.

Si el código fue el siguiente aspecto:

Foo foo = new Foo(); 
foo.Say() 

El método Foo.Say() serían ejecutados, no es el método de extensión.

Ojalá pudiera darle una explicación detallada de por qué esto es así, pero solo puedo cubrir el mecanismo básico. Como su variable era del tipo IFoo y no de Foo, cuando el compilador intentó determinar qué métodos estaban disponibles, miró más allá de los métodos que no eran de interfaz de la clase Foo (como debería). Sin embargo, el método de extensión Say() estaba disponible, por lo que invocó esto.

+2

Para agregar a esto , cuando usas 'IFoo foo = ..', el tipo de foo es' IFoo' a pesar de que apunta a una instancia de 'Foo'. 'Foo foo ...' llama al método sobre el objeto, 'IFoo foo' hace que' Say() 'se expanda a' FooExts.Say (foo) '. Ejecute 'ildasm' y suelte el .exe en él para ver el IL. –

+0

Gracias Jim buen consejo. – Dax70

4

En su Main, se ha declarado IFoo Cuando el compilador busca un método Say, encuentra solo el método de extensión. Esto se debe a que el método de instancia se declara en Foo, no en IFoo. El compilador no sabe que la variable foo contiene una instancia de Foo; solo mira el tipo de declaración de la variable.

Cuestiones relacionadas