2012-08-24 19 views
11

Mam klasa bazowa Ametody Dlaczego przeciążony ma niższy priorytet niż metody instancji

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

klasa statyczna S metodą wydłużania

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

Przykład tworzymy instancję typu B i wywołaj na nim Method, spodziewamy się, że będzie to public override void Method(B parameter) rzeczywisty wynik to public virtual void Method(object parameter).

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

Dlaczego kompilator nie wybiera bardziej odpowiedniej metody ??? UPD I dlaczego nie jest to metoda rozszerzenia?

+3

'B' nie jest zagnieżdżony, ale dziedziczony. –

+0

@Henk Holterman dzięki – user854301

+0

metoda rozszerzenia nie jest wywoływana, jeśli obiekt ma metodę o tej samej nazwie. ma to na celu uniknięcie zerwania starego kodu, gdy oczekiwaniem jest wywołanie starej metody, a nie nowego rozszerzenia. – Ankush

Odpowiedz

10

Dlaczego kompilator nie wybiera bardziej odpowiedniej metody?

Bo to jest zgodnie z zasadami zawartymi w specyfikacji języka, gdzie wszelkie metody kandydujące pierwotnie zadeklarowanej w klasie bazowej (na razie są one zmienione w klasie pochodnej) są ignorowane, gdy znalezienie sposobu kandydata, chyba że klasa pochodna nie ma żadnych odpowiednich metod, w którym to momencie wyszukiwanie przenosi się do klasy podstawowej, itp.

To jest designed to avoid the "brittle base class" problem, ale uważam, że trudno to przełknąć w obliczu nadpisania metody w pochodnej klasa.

Odpowiednie nieco specyfikacji C# 4 wynosi 7,4, która kończy się w ten sposób:

Do sprawdzania członkowskich typów innych niż parametry i interfejs typu i wyszukiwań składowych znajdujących interfejsów, które są ściśle jednego dziedziczenia (każdy interfejs w łańcuchu dziedziczenia ma dokładnie zero lub jeden bezpośredni interfejs bazowy), efekt reguł wyszukiwania polega po prostu na tym, że członkowie pochodni ukrywają podstawowe elementy o tej samej nazwie lub sygnaturze.

EDIT: O rozszerzenie metod ...

A dlaczego nie jest to metoda rozszerzenie?

Z sekcji 7.6.5.2 spec:

W o wywołaniu metody (§7.5.5.1) jednej z postaci

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

gdy normalne przetwarzanie wywołania nie znajduje odpowiednich metod, podjęto próbę przetworzenia konstruktu jako inwokacji metody rozszerzenia

Tak więc Metoda rozszerzenia jest w zasadzie używana tylko w ostateczności jako .

+0

Myślę, że pytanie brzmi: dlaczego kod wywołuje metodę dziedziczenia, a nie metodę rozszerzenia, ale trudno powiedzieć? – podiluska

+0

@podiluska: Myślę, że metodą rozszerzenia jest czerwony śledzia. OP wydaje się nie oczekiwać, że zostanie nazwany ... –

+0

Interesujące jest również, dlaczego metoda rozszerzenia nie jest nazywana. – user854301

Powiązane problemy