Methoden Überladen (Lösung)

Auflösung:

Es wird „Derived.Foo(object)“ ausgegeben.
Warum ist dies so?

Der C# Compiler wählt die neu implementierte Methode Foo(object) anstelle der überschriebenen Methode Foo(int), unter der Massgabe das die übergebenen Parameter kompatibel sind. Dies liegt daran, dass überschriebene Methoden nicht als Klassendeklaration betrachtet werden, sondern als neue Implementierungen einer Methode, welche in einer Basisklasse deklariert ist. Kurz gesagt, durchsucht der Compiler erst die direkt deklarierten Methoden von Derived, dann die Methoden von Base die in Derived überschrieben sind und dann die Methoden von Base.

Das heißt, dass folgender Code zum gleichen Ergebnis führt:

namespace ConsoleApplication1
{
    class Base
    {
        public virtual void Foo(int x)
        {
            Console.WriteLine("Base.Foo(int)");
        }
    }

    class Derived : Base
    {
        public void Foo(object o)
        {
            Console.WriteLine("Derived.Foo(object)");
        }
    }

    class Program
    {
        static void Main()
        {
            Derived d = new Derived();
            int i = 10;
            d.Foo(i);
        }
    }
}

Wie kann man das vermeiden?

1. Da die Gleichbenamung eh ein suboptimaler Stil ist, sollte man einen anderen Namen vergeben!

2. Per Code und explizitem Casting gehts natürlich auch. Hier wird die Methodenliste von Base durchsucht um eine kompatible Methode zu finden. Da Foo virtuell ist, wird die Implementierung von Foo(int x) in Derived aufgerufen.

namespace ConsoleApplication1
{
    class Base
    {
        public virtual void Foo(int x)
        {
            Console.WriteLine("Base.Foo(int)");
        }
    }

    class Derived : Base
    {
        public override void Foo(int x)
        {
            Console.WriteLine("Derived.Foo(int)");
        }
    

        public void Foo(object o)
        {
            Console.WriteLine("Derived.Foo(object)");
        }
    }

    class Program
    {
        static void Main()
        {
            Derived d = new Derived();
            int i = 10;
            ((Base)d).Foo(i);
        }
    }
}

Es gibt noch eine weitere Möglichkeit, die ich zwar nicht wirklich unterstütze, aber der Vollständigkeit halber erwähne. Man kann die Implementierung der Basisklasse verbergen und die Methode als Deklaration der Derived Klasse bauen. Hierfür gibt es das Schlüsselwort „new“.

namespace ConsoleApplication1
{
    class Base
    {
        public virtual void Foo(int x)
        {
            Console.WriteLine("Base.Foo(int)");
        }
    }

    class Derived : Base
    {
        public new void Foo(int o)
        {
            Console.WriteLine("New Derived.Foo(int)");
        }

        public void Foo(object o)
        {
            Console.WriteLine("Derived.Foo(object)");
        }
    }

    class Program
    {
        static void Main()
        {
            Derived d = new Derived();
            int i = 10;
            d.Foo(i);
        }
    }
}

Gemäß dem oben beschriebenen Mechanismus der Methodenauswahl wird hier eine geeignete Methode innerhalb von Derived gesucht und mit Foo(int) auch gefunden, da diese Teil der Klassendeklaration ist.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert