Frage

Ich habe den folgenden Code

class Program
    {
        static void Main(string[] args)
        {
            List<A> aList = new List<A>();

            var aObj = new A();

            aObj.Go(aList.Cast<IB>());
        }
    }

    class A : IB
    {
        public void Go(IEnumerable<IB> interfaceList)
        {
            foreach (IB ibby in interfaceList)
            {
                Console.WriteLine("Here");
            }
        }
    }

    interface IB
    {
        void Go(IEnumerable<IB> interfaceList);
    }

}

Ich habe versucht, die ursprünglich eine Liste vorbei, aber das funktioniert nicht . Nach einer viel Hilfe von SO fand ich, dass IEnumerable vorbei das ist nur so können die Objekte über als .ofType (IB) zu erhalten.

Leider ist für mich, in meinem Code die folgende Zeile wird ausgeführt tausende Male werden:

aList.Cast<IB>();

Ich habe mich gefragt, ob jemand weiß, wie es algorithmisch umgesetzt wurde (in IL) und der, was seine Zeit um ist.

Das heißt, es ist schneller als eine foreach-Schleife, die nur jedes Element wirft, oder ist das genau das, was sie tut?

Bearbeiten Die Hauptklasse muss eine Liste der tatsächlichen Objekte erhalten. Aber der Leser ist nur erlaubt, sie über die Schnittstelle zu berühren.

War es hilfreich?

Lösung

Sie sollten ändern Go an:

public void Go<T>(IEnumerable<T> interfaceList)
    where T : IB
{
    foreach (IB ibby in interfaceList)
    {
        Console.WriteLine("Here");
    }
}

Dann werden Sie ohne die Notwendigkeit, in Ordnung sein Cast zu nennen. Ich vermute, dass die Quellcode Implementierung von Cast ist ziemlich einfach, obwohl ich es geändert zwischen 3,5 und 3.5SP1 glauben. Allerdings muss es wohl eine neue Zustandsmaschine usw. im normalen Iteratorblock Art und Weise einzurichten. Besser ist es wenn möglich zu vermeiden.

Auch wenn die neue Methode generisch ist, Typinferenz sollte in der Regel für Sie darum kümmern, so dass Sie müssen nicht explizit angeben T.

Andere Tipps

Warum nicht einfach erklären, die Liste wie:

List<IB> aList = new List<IB>();

Gibt es etwas Bestimmtes, dass Sie eine Liste der konkreten Klassen haben, erfordert?


Also in diesem Fall würde ich die Liste Teil der Domäne machen. Haben Sie eine Schnittstelle wie IIBCollection (zum Beispiel), setzt die Methoden auf, dass Sie den Leser des Zugangs zu der Lage sein wollen. Zum Beispiel:

interface IIBCollection{
    IEnumerable<IB> IBs { get; }
}

// and in your implementation you can do

IEnumerable<IB> IBs { 
    get { 
        foreach(IB ib in innerList) yield return ib; 
}}

Es wird intern als CastIterator implementiert, die etwas langsamer als ein foreach ist, dass jedes Element wirft.

Die Gussverfahren werden nur Schleife durch die Liste und werfen jedes Element.

Wenn Sie die Liste Tausende von Zeit verwenden wollen, speichern Sie einfach das Ergebnis des Gusses als Liste an.

Wenn das nicht möglich ist (das heißt Sie die Liste ändern jedes Mal), sollten Sie mit einem List<IB> arbeiten anstelle eines List<A>.

Ist das nicht das, was Kovarianz in C # für ist? Ich sehe nicht, was Sie versuchen, zu tun, so kann ich nicht kommentieren, warum es exeuted Tausende und Abertausende von Zeiten.

Es wäre eine ziemlich einfache Sache sein, nur die beiden Methoden (Cast-Extension-Methode und eine for-Schleife mit einer Besetzung) zum Benchmark. Aber da Cast ist eine Erweiterung Methode der Enumerable-Klasse und befasst sich allgemein mit IEnumerables, würde ich vorstellen, das ist genau das ist es Implementierung. Wenn Sie die größte Geschwindigkeit wollen, kann es am besten sein, eigene Erweiterungsmethode zu implementieren, die speziell auf Liste arbeitet (wird jedes Element durch seinen Index), die schneller leicht den Aufwand für Iteratoren gegeben werden sollte. Dennoch sollten beide Methoden O (n) Zeit in Anspruch nehmen, so dass der Unterschied soll nicht sehr groß sein. Es ist etwas wert Benchmarking, dennoch ...

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