2011-09-22 20 views
12

Sono un po 'confuso su come funzionano i metodi di estensione.C# Precedenza metodo estensione

Se sto leggendo correttamente questo http://msdn.microsoft.com/en-us/library/bb383977.aspx e questo If an extension method has the same signature as a method in the sealed class, what is the call precedence?.

Quindi quanto segue dovrebbe scrivere "Istanza", ma invece scrive "Metodo di estensione".

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(); 
    } 
} 

Apprezzare qualsiasi aiuto nel chiarire il comportamento.

+0

Sei sicuro di sovrascrivere un metodo integrato con un metodo di estensione compilato? – kenny

+0

A prima vista o compilandolo, l'interfaccia non ha Say(), quindi quello che hai chiamato il metodo di estensione. Con Save() nell'interfaccia il compilatore si lamenta con 'C: \ projects \ _play \ ExtensionMethods \ Program.cs (2,1): errore CS0116: Uno spazio dei nomi non può contenere direttamente membri come campi o metodi' – kenny

risposta

14

La grande differenza è che è stato definito un metodo di estensione per l'interfaccia IFoo e la variabile foo è di tipo IFoo.

Se il codice è stato quello di simile a questa:

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

Il metodo Foo.Say() sarebbero stati giustiziati, non il metodo di estensione.

Vorrei poterti dare una spiegazione esauriente sul motivo per cui questo è, ma posso solo coprire il meccanismo di base. Poiché la variabile era di tipo IFoo e non di Foo, quando il compilatore ha cercato di determinare quali metodi erano disponibili, ha guardato oltre i metodi non di interfaccia della classe Foo (come dovrebbe). Tuttavia, il metodo di estensione Say() era disponibile, quindi ha invocato questo.

+2

Per aggiungere a questo , quando usi 'IFoo foo = ..', il tipo di foo è' IFoo' anche se punta a un'istanza di 'Foo'. 'Foo foo ...' chiama il metodo sull'oggetto, 'IFoo foo' fa sì che' Say() 'si espanda a' FooExts.Say (foo) '. Esegui 'ildasm' e rilascia l'exe per vedere l'IL. –

+0

Grazie Jim buon consiglio. – Dax70

4

Nel Main, foo è dichiarato come IFoo. Quando il compilatore cerca un metodo Say, trova solo il metodo di estensione. Questo perché il metodo di istanza è dichiarato in Foo, non in IFoo. Il compilatore non sa che la variabile foo contiene un'istanza di Foo; guarda solo il tipo di dichiarazione della variabile.