Frage

Es gibt ein paar Stellen bereits auf Stack-Überlauf über diese Art der Sache, aber nicht genau die gleiche - so Entschuldigungen im Voraus, wenn dies etwas, das bereits beantwortet wurde

.

Warum funktioniert das nicht:

public class MyBase { }

public class MyUtils
{
    public bool Foo<T> (T myObject) { return true; }
    public bool Foo (MyBase myBaseObject) { return false; }

    public void Go<T> (IEnumerable<T> items)
    {
        foreach (var item in items)
        {
            // this test fails
            Assert.IsFalse (Foo (item));
        }
    }
}

Wenn ich rufe Go () oben und in einer Last von MyBase Objekte bewegen, wird jeder Aufruf Foo wird die generische Foo () aufrufen, die true zurückgibt.

new MyUtils ().Go (new MyBase[] { new MyBase (), new MyBase () });      

Warum nennen Sie es nicht die spezialisierte MyBase Version statt? Wenn ich Foo (neu MyBase ()) direkt anrufen, es folgert richtig was Anruf zu tätigen. Ist dies wegen der fehlenden Kovarianz für Sammlungen in C # 3, oder bin ich nur dumm zu sein und nicht das richtig tun?

Danke!

Isaac

War es hilfreich?

Lösung

Es ist nicht nennen sich die „spezialisiert“ ein, da der Compiler die Methode aufrufen choses, wenn das Programm (die in diesem Fall die Go Funktion ist) ist zusammengestellt , nicht , wenn es ausgeführt werden.

Wenn die Compiler die Go Funktion kompiliert wird, die einzige Information, es hat ist, dass es einige Objekte vom Typ T. Es hat keine Idee, dass Sie zu einem späteren Zeitpunkt mit einem Objekt vom Typ MyBase liefern können. Die einzige Option ist die Foo<T> Überlastung, zu wählen und so backt es, dass in dem kompilierte Programm.

Wenn Sie eine Anwendung mögen Überlastungen während der Laufzeit zu wählen, und wählen Sie die beste Überlastung durch im Objekt betrachtet, während die Anwendung ausgeführt wird, ist, dass „dynamische Dispatch“ genannt, und nur durch dynamische Sprachen wie Ruby verwendet wird, Python, PHP, usw.

C # 3 ist voll statisch und dies nicht unterstützt. Sie müßten eine if-Anweisung in Ihrem Code schreiben, um die Art zu überprüfen, ob man es wollte auf diese Weise arbeiten. C # 4 auf der anderen Seite, hat einige dynamische Unterstützung. Wenn Sie diesen Code in C # 4 wurden zu schreiben, könnten Sie die ‚Go‘ Funktion erklären, wie folgt:

 public void Go<T> (IEnumerable<dynamic> items)

Dann wäre es dynamische Dispatch zur Laufzeit verwenden, um auszuwählen, welche aufgerufen wird, übermäßig zu belasten, und würde die Überlastung spezialisiert rufen MyBase nehmen

Andere Tipps

Nach C # Spezifikationen (7.4.3.2), die nicht-generische Methode ist besser als die generische, so sollte es ausgewählt werden.

Aber ich denke, das generisch man in Ihrem Fall aufgenommen, weil es in einem allgemeinen Aufrufkontext (der „foreach“ Loop) genannt wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top