9 Stimmen

Warum werden in der Basisklasse deklarierte Signaturen ignoriert?

class Base
{
    public virtual void MethodA(int x)
    {
        Console.WriteLine ("In Base Class");
    }
}

class Derived : Base
{
    public override void MethodA(int x)
    {
        Console.WriteLine ("In derived INT)");
    }

    public void MethodA(object o)
    {
        Console.WriteLine ("In derived OBJECT");
    }
}

class Test
{
    static void Main()
    {
        Derived d = new Derived();
        int k = 20;
        d.MethodA(k);
    }
}

Die Ausgabe, die ich dafür erhalte, ist " In abgeleitetem OBJECT ". Was ist der Grund für dieses seltsame Verhalten? Nach einigen Nachforschungen habe ich herausgefunden, dass der Grund ist die in der Basisklasse deklarierten Signaturen werden ignoriert . Warum werden sie ignoriert?

1 Stimmen

+1 zur Frage: Ich stimme zu, dass dies ein kontra-intuitives Verhalten ist.

0 Stimmen

Ich stimme zu, dass das Verhalten seltsam ist. Ich möchte wissen, ob Sie diese Frage stellen, weil Sie dies tatsächlich tun wollen, oder weil Sie neugierig waren? Ich sehe keinen Grund, so etwas tatsächlich zu implementieren, aber ich würde auf jeden Fall gerne wissen, warum es passiert.

0 Stimmen

7voto

Eric Lippert Punkte 628543

Das ist so gewollt und hat einen guten Grund. Dieses Design hilft, das Problem der spröden Basisklassen zu vermeiden. C# wurde entwickelt, um es einfacher und sicherer zu machen, "versionierte" Komponenten zu schreiben, und diese Regel ist ein wichtiger Teil davon.

Dies ist eine sehr häufig gestellte Frage. Dies ist eine der häufigsten "falschen Fehlerberichte", die wir erhalten, d.h. jemand glaubt, einen Fehler im Compiler gefunden zu haben, obwohl er in Wirklichkeit eine Funktion gefunden hat.

Eine Beschreibung der Funktion und warum sie so konzipiert ist, finden Sie in meinem Artikel zu diesem Thema:

http://blogs.msdn.com/b/ericlippert/archive/2007/09/04/future-breaking-changes-part-three.aspx

Weitere Artikel zum Thema, wie verschiedene Sprachen mit dem Problem der spröden Basisklasse umgehen, finden Sie in meinem Archiv mit Artikeln zu diesem Thema:

http://blogs.msdn.com/b/ericlippert/archive/tags/brittle+Basis+Klassen/

2voto

mjfgates Punkte 3291

Der Compiler in VC# 2008 prüft die verfügbaren nicht-virtuellen Funktionen vor den virtuellen, wenn er entscheidet, was aufgerufen werden soll. Da Ihre abgeleitete Klasse eine nicht-virtuelle MethodeA(object) hat, die aufgerufen werden kann, ruft der Compiler sie auf.

Wenn man eine virtuelle MethodeA(object) zu Base hinzufügt, dann wird Derived.MethodA(int) aufgerufen, weil dann sowohl MethodA(object) als auch MethodA(int) virtuell sind.

Ich bin nicht vertraut genug mit der C#-Sprachenspezifikation, um zu wissen, ob dies ein spezifiziertes Verhalten oder ein Fehler im Compiler ist.

0 Stimmen

In der ECMA-Spezifikation steht tatsächlich, dass nicht-virtuelle Anwendungen zuerst aufgerufen werden. Beachten Sie auch, dass die Methode, die aufgerufen wird, bei nicht-virtuellen Methoden vom Compiler und bei virtuellen Methoden vom Laufzeittyp bestimmt wird.

0 Stimmen

Ich habe das überprüft, aber beachten Sie, dass Derived.MethodA(int) nur aufgerufen wird, wenn Sie das Schlüsselwort 'override' zu Derived.MethodA(object) hinzufügen (das war natürlich gemeint). Ohne dieses Schlüsselwort wird das optionale Schlüsselwort "new" angenommen und Derived.MethodA(object) wird weiterhin aufgerufen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X