Mit Hilfe von Generischen Containern in Delphi XE - immer?
Generische Container kann eine Zeitersparnis, wenn Sie ein Element, und eine stark typisierte Liste dieser Elemente. Es erspart die wiederholte Programmierung erstellen Sie eine neue Klasse mit vielleicht einer TList internen Variablen und typisierte Hinzufügen/Löschen, geben Sie Methoden, unter anderen Vorteile (wie die neue Funktionalität zur Verfügung gestellt durch die Generische container-Klassen.)
Jedoch ist es empfohlen, immer die Verwendung generischer Container für stark typisierte Listen der Zukunft an? Was sind die spezifischen Nachteile, dies zu tun? (Wenn Sie nicht besorgt über die Abwärtskompatibilität von code.) Ich war das schreiben einer server-Anwendung gestern und hatte eine Liste der Gegenstände, die ich erstellt 'der alte Weg' und ging, um es zu ersetzen mit einer generischen Liste, aber beschlossen, es zu halten, lean, aber meistens aus Gewohnheit. (Sollten wir diese Gewohnheit abzulegen und eine neue zu beginnen, indem Sie immer mit generics?)
- Aus den eingegangen Antworten wurde dies ist ein Beispiel, warum StackOverflow ist so gut!
Du musst angemeldet sein, um einen Kommentar abzugeben.
In Delphi XE, gibt es keinen Grund für die Verwendung generischer Container.
Wechsel von der alten Methode mit dem Gießen geben Sie:
die gleichenbessere Fahreigenschaften.TSomethingList = class(TObjectList<TSomething>)
: Diejenigen Klassen, die früher existierten als hand-schriftliche Nachkommen vonTObjectList
aber wandte sich nun in Generika Behälter, so dass ich verwenden können, diefor in
Schleife.Auslöser war Deltic Antwort, ich wollte ein Gegenbeispiel beweisen, können Sie Generika für die Tierische Fütterung routine. (ie: Polymorph-Generische Liste)
Zunächst einige hintergrund: Der Grund, warum Sie ernähren können generische Tiere mit einem generischen Basis-Liste ist Klasse, da werden Sie in der Regel diese Art von Vererbung:
Das funktioniert nicht mit Generika, weil Sie normalerweise haben diese:
... und das nur "gemeinsame Vorfahren" für beide Listen ist
TObject
- überhaupt nicht hilfreich. Aber wir können definieren, eine neue, generische Liste Typs, der zwei-Klassen-Argumente: eineTAnimal
und einTSpecificAnimal
generieren eine typsichere Liste derTSpecificAnimal
kompatibel mit einem generischen Liste derTAnimal
. Hier ist die grundlegende Art definition:Mithilfe dieser können wir tun:
Diese Weise sowohl TDogList und TCatList tatsächlich Erben von
TObjectList<TAnimal>
, so haben wir jetzt eine polymorph-generische Liste!Hier ist eine komplette Konsole-Anwendung, die zeigt, dass dieses Konzept in Aktion. Und diese Klasse ist jetzt in meinem ClassLibrary für die Wiederverwendung!
Sollten wir diese Gewohnheit abzulegen und eine neue zu beginnen, indem wir immer die Verwendung von Generika?
JA
In den meisten Fällen, ja, generische Container sind eine gute Sache. Allerdings der compiler erzeugt viel doppelten code, und leider ist der linker nicht weiß, wie Sie es noch so starker Einsatz von Generika könnten die Folge einer Aufblähung der ausführbaren Datei. Aber anders als das, Sie sind groß.
In den Geist von Cosmin Antwort, die im wesentlichen eine Reaktion auf die Deltic ' s Antwort, hier ist, wie zu beheben Deltic code:
Nun kann man schreiben:
TAnimalList<TDog>
erbt vonTList<TDog>
und erbtTObject
. Sie können nichtvar L:TList<TAnimal> := TAnimalList<TDog>.Create
ist das nicht eine polymorphe Liste."If you need polymoprhic lists then Generics are a hindrance"
.Add
undGetItem
Methoden. Die Laufzeit-Komplexität ist, dass der "alte Buch" Handbuch getter Neudefinition. Mit ist es genauso einfach wie mit jedem anderen generischen container.TList<TAnimal>
. In der Tat bin ich ein Buch zu Lesen aufasp.net
gerade jetzt, wo der Autor sagt:polymorphism is the most talked about and least useful feature
(stark umformuliert, weil ich nicht das Buch bei mir und ich bin mir auch nicht sicher, ob der Autor redete über OOP im Allgemeinen oder nur die asp.net framework). (Fortsetzung folgt...)(TList<TControl>)
mit(TList<TMyFrame>
ist nicht möglich; DochTMyFrame
erbt vonTControl
und die erste routine kann angewendet werden, um die Liste der frames. Hätten wir eine polymorphe Liste derTMyFrame
erbtTList<TControl>
wären wir in der Lage, um die routine. Tut mir Leid, wenn das klingt weit hergeholt, aber Polymorphie ist in sich selbst hoch "verbose" und setzen Sie eine andere Ebene der OOP-ish Polymorphismus oben drauf macht es nur Ausführlicher.Sie schrieb über die rückwärts-Kompatibilität... das ist meine größte Sorge, wenn (wie ich) Sie schreiben, die Bibliotheken, die sollten besser kompilieren mit den meisten gängigen Versionen von Delphi.
Selbst wenn Sie nur XE für ein geschlossenes Projekt, sind Sie wahrscheinlich machen einige benutzerdefinierte Bibliotheken von Ihrem eigenen, auch wenn Sie nie veröffentlichen den code. Wir alle haben solche Lieblings Einheiten bei der hand, nur nicht das Rad neu erfinden für jedes Projekt.
In einer zukünftigen Zuordnung, die Sie haben können, weiterhin etwas älterer code, ohne die Möglichkeit, ein upgrade auf eine neuere Delphi-version (kein Geld für 1.000.000 Codezeilen, migration und Kritik). In diesem Fall, verpassen Sie Ihren XE-nur Bibliotheken mit glänzenden generic-basierte Listen...
Aber für eine 100% "private" Anwendung, wenn Sie sicher sind, dass Sie nie haben, pflegen ältere Delphi-code, ich sehe keinen Grund, nicht zu verwenden Generika. Meine einzige Sorge ist der duplizierten code Problem (zitiert von Mason): der CPU-cache gefüllt werden kann mit unnötigen code, sodass die Ausführung Geschwindigkeit könnte darunter leiden. Aber in der realen app, ich denke, dass Sie nicht sehen, keinen Unterschied.
Hinweis: ich habe nur Hinzugefügt, einige neue Funktionen auf meiner TDynArray wrapper. Ich habe versucht, zu imitieren,der Beispielcode von EMB docwiki. So hätte man generic-ähnliche Funktionen, mit der guten alten Delphi-Versionen... natürlich, Generika sind besser für die Arbeit mit Klassen, sondern mit einigen arrays und records, die es nur Felsen!
Delphi (N+1)
box, die wir kennen, die wir verwenden Funktionen, die nicht verfügbar inDelphi (N)
- das ist, warum wir kauftenDelphi (N+1)
Wenn Sie brauchen, polymoprhic Listen dann Generika sind ein Hindernis, keine Hilfe. Diese nicht selbst kompilieren, zum Beispiel, weil Sie nicht verwenden können, eine TDogList, wo ein TAnimalList ist erforderlich:
Die Gründe dafür sind ziemlich klar und leicht zu erklären, aber es ist gleichermaßen counter-intuitive.
Meine eigene Ansicht ist, dass Sie sparen ein paar Sekunden oder Minuten (wenn Sie eine langsame schreibkraft) durch die Verwendung eines generischen anstatt zu Rollen eine typsichere container mehr spezifische und für Ihre Bedürfnisse geeignet, aber Sie können am Ende verbringen mehr Zeit mit der Arbeit rund um die Probleme und Beschränkungen von Generika in die Zukunft, als Sie gerettet, indem er Sie, mit zu beginnen (und per definition, wenn Sie nicht mit generischen Containern bis zu jetzt, da Sie nicht wissen, was diese Probleme/Einschränkungen könnte, bis Sie laufen in Ihnen).
Wenn ich eine TAnimalList dann sind die Chancen, die ich brauchen oder davon profitieren könnten zusätzliche TAnimal spezifische Methoden auf, die Liste Klasse, die würde ich gerne Erben in einem TDogList, was wiederum einen zusätzlichen spezifischen Mitglieder relevant es ist TDog Elemente.
(Tier und Hund genutzt, nur zur Veranschaulichung, natürlich. Ich weiß nicht wirklich Arbeit auf Tierarzt-code aktuell LOL)
Das problem ist, dass du nicht immer wissen, an den start.
Defensive Programmierung an den Prinzipien vorschlagen (für mich ymmv), dass die Malerei selbst in eine Ecke zuliebe ein bisschen Zeit sparen ist wahrscheinlich am Ende kostet eine Menge in der Zukunft. Und wenn es nicht die zusätzlichen "Kosten" des nicht unter die up-front-sparen ist an sich vernachlässigbar.
Plus Ihr code ist mehr shareable mit Benutzern von älteren Delphi-Versionen, wenn Sie geneigt sind, so großzügig sein.
🙂
TList<T>
im wesentlichen erbt direkt vonTObject
)