2 Stimmen

Ist der Konstruktor einer Klasse, die von einer anderen Klasse erbt, weniger effektiv?

Frage

In meiner Anwendung erstelle ich eine große Anzahl von Instanzen der "kleinen" Klasse, die nur einige Daten enthalten.

Ich weiß, dass die Erstellung einer Klasse (d. h. der Aufruf eines Konstruktors) kostspielig ist. Meine Frage ist: Wird es kostspieliger sein, wenn ich diese kleine Klasse von einer anderen Klasse erben lasse? Einige Felder werden einfach in die Superklasse verschoben, also kann ich im Grunde nur

Hinweis: Diese Frage bezieht sich speziell auf die Leistung in .NET .


Beispielsituation und Demonstration der Frage

Betrachten Sie diese 2 Fälle:

1. Fall besteht nur aus einer Klasse. Es ist die ursprüngliche Klasse:

public class ShapeWithOffset{
    public double XOffset { get; private set; }
    public double YOffset { get; private set; }
    public IShape Shape{ get; private set; }

    public ShapeWithOffset(double xOffset, double yOffset, IShape shape){
        //check if arguments are correct/throw ArgumentException if not
        XOffset = xOffset;
        YOffset = yOffset;
        Shape = shape;
    }
    //equality members
}

2. Fall besteht aus 2 Klassen, wobei die zweite von der ersten erbt. Zweite Klasse ShapeWithHorizontalAndVerticalOffset bietet die gleiche Funktion wie ShapeWithOffset im 1. Fall.

public class ShapeWithHorizontalOffset{
    public double XOffset { get; private set; }
    public IShape Shape { get; private set; }

    public ShapeWithHorizontalOffset(double xOffset, IShape shape){
        //check if arguments are correct/throw ArgumentException if not
        XOffset = xOffset;
        Shape = shape;
    }
    //equality members
}

public class ShapeWithHorizontalAndVerticalOffset : ShapeWithHorizontalOffset{
    public double YOffset { get; private set; }

    public ShapeWithHorizontalAndVerticalOffset(double xOffset, double yOffset, 
                                                IShape shape) : base(xOffset, shape){
        //check if yOffset is correct/throw ArgumentOutOfRangeException if not
        Yffset = yOffset;
    }
    //equality members
}

Meine Frage ist: Ist der Befehl var foo = new ShapeWithOffset(20, 10, shape); schneller als
var boo = new ShapeWithHorizontalAndVerticalOffset(20, 10, shape); ?

Wenn ich Komposition anstelle von Vererbung verwenden würde, wäre es... Aber was ist mit der Vererbung?

8voto

Daniel Renshaw Punkte 32893

Das riecht wie vorzeitige Optimierung

Die Schlüsselwörter in Ihrer Frage sind "... ich denke ...". Wenn Sie wissen, dass Sie ein Leistungsproblem haben, sollten Sie den Engpass ermitteln und diesen optimieren. Wenn Sie ein Leistungsproblem erwarten, lassen Sie es bleiben! Es ist äußerst unwahrscheinlich, dass ein Leistungsengpass durch die Verwendung von Vererbung in der von Ihnen vorgeschlagenen Weise verursacht wird. Aber wenn Sie es wirklich im Voraus wissen wollen, testen Sie im Voraus.

5voto

Jakub Míšek Punkte 1019

Das wird fast dasselbe sein. Der Aufruf des Basis-.ctors wird von JITter inlined und die Zuweisung wird nur einmal durchgeführt. Das kostet Sie nur ein paar Bytes als Overhead.

Wenn Sie sich nicht sicher sind, versuchen Sie es mit einem kleinen Benchmark.

3voto

Dan Bryant Punkte 27022

Meine Erfahrung mit der Mikro-Optimierung von Code mit einem Profiler ist, dass der Overhead bei Methodenaufrufen vernachlässigbar ist. Meine Hauptgewinne für Leistungsverbesserungen waren fast immer: Zwischenspeicherung häufig verwendeter Berechnungen, Optimierung tiefer innerer Schleifen (in der Regel durch direkte Array-Indizierung anstelle von Aufzählungen) und Vermeidung unnötiger Boxings. All dies wird natürlich durch die Verbesserung des Algorithmus zur Verringerung der Anzahl der Iterationen in den Schatten gestellt (in der Regel durch die Einführung einer Heuristik, mit der Verzweigungen frühzeitig ausgeschlossen werden können, oder durch die Umwandlung des Problems in getrennte 'Aggregat'- und 'Detail'-Phasen).

1voto

Frédéric Hamidi Punkte 249635

Erstens, wie ich in meinem Kommentar sagte, beeinträchtigt der Aufruf von Basiskonstruktoren (und virtuellen Methoden) die Leistung nicht genug, um den Verlust der Wartbarkeit und Ausdruckskraft zu rechtfertigen, die er Ihrem Programm verleiht. Wenn die Leistung in diesem Fall wirklich ein Problem wäre, gäbe es keine strukturierten Sprachen.

Nun, von einer Entwurf Die Frage reduziert sich auf die Frage, ob sich eine Vererbung in Ihrem Fall tatsächlich lohnt oder nicht. Daraus ergibt sich die Frage: Warum kann man nicht ShapeWithOffset entstammen Shape ? Wenn es möglich wäre, würde ich wahrscheinlich die Komplexität abschneiden und etwas wie:

public class ShapeWithOffset : Shape
{
    public ShapeWithOffset(double xOffset)
    : this(xOffset, 0.0) {}

    public ShapeWithOffset(double xOffset, double yOffset)
    {
        // TODO - Check if arguments are correct/throw ArgumentException if not.
        XOffset = xOffset;
        YOffset = yOffset;
    }
}

In C# 4 können Sie sogar schreiben:

public ShapeWithOffset(double xOffset, double yOffset = 0.0)
{
    // TODO - Check if arguments are correct/throw ArgumentException if not.
    XOffset = xOffset;
    YOffset = yOffset;
}

0voto

MoienGK Punkte 4346

Sprechen im Allgemeinen über Vererbung (nicht speziell dieser Ihren Fall) als Kuchana sagte in seinem Buch (Design Patterns) versuchen, Vererbung zu vermeiden, wenn nicht notwendig, wegen seiner Komplexität. und ich denke, dass Laufzeit-Bindung kann in kleinen Performance-Probleme verursachen, aber die wichtigsten Overhead der Vererbung ist seine Komplexität in Design, das ist viel wichtiger als eine winzige Performance-Problem.

エディテージ

Ich weiß jetzt, dass die Frage sich auf das Konstruieren bezieht :D. der folgende Absatz ist in Java wahr, vielleicht ist er auch in .Net wahr. Ich denke, wenn du explizit einen Konstruktor in deiner Kindklasse definierst, wird es keinen Unterschied machen, weil der Compiler zuerst nach einem Konstruktor in der Kindklasse suchen wird, wenn er ihn nicht findet, wird er in der Vererbungshierarchie nach oben gehen, bis er den richtigen Konstruktor findet.

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