Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Generic Graph class (https://www.delphipraxis.net/183727-generic-graph-class.html)

bernhard_LA 30. Jan 2015 20:55

Generic Graph class
 
die aktuelle Verion meiner Graphen Klasse incl. Generic#s sieht wie folgt aus

Delphi-Quellcode:
  TNetGraph<T> = Class

  public

    fList : TNetList;
    G: TGraph<T>;

    constructor create(g_type: TGraphEdgeMode = normal_directed);
    destructor destroy; override;

    function GetNetitem(aData: T): TNetItem;


function TNetGraph<T>.GetNetitem(aData: T): TNetElement;
begin

  if (T(adata) is integer) then
       result := fList.Items[integer(T(aData))]     ///  geht so nicht :-( 
  end;
 
end;
...
 End;

ich scheitere an einer Abfrage um welchen Datentypen es sich bei aData handelt und dem entsprechende auf den ZUgriff in meine Liste fList zu reagieren.

Harry Stahl 30. Jan 2015 23:28

AW: Generic Graph class
 
Erst mal fällt mir auf, dass in Deiner Klassendefinition die Fuktion "GetNetItem" als Result "TNetItem" hat, in der Implementation aber "TNetElement".

Den Typ für aData, bzw. "T" kannst Du so abfragen:

Delphi-Quellcode:
if (GetTypeName (Typeinfo (T)) = 'Integer') then begin
  ...
end;
Den Integerwert selbst kannst Du so ermitteln:

Delphi-Quellcode:
  result := fList[PInteger (@adata)^];

bernhard_LA 31. Jan 2015 09:55

AW: Generic Graph class
 
T kann als Datentyp alles mögliche sein , wenn ich als "integer type" definiere kann ich mit


Delphi-Quellcode:
flist.Items[data]
direkt zugreifen.


Mir wäre ein Vergleich auf den Datentyp selbst am liebsten . Udn nochbesser ein case Statement in diesem Form



Delphi-Quellcode:
    case data as Datatype of
    integer:
    TMyCustomDataType_1 :
        begin
        ...
        end;
     TMyCustomDataType_2 :
     TMyCustomDataType_3 :
    else
     end;

geht soetwas mit Delphi ?



Alternative Ziel Option mit if Statement


Delphi-Quellcode:
  if data is integer then
      begin

      end;

Dejan Vu 31. Jan 2015 10:17

AW: Generic Graph class
 
Da ein case-Statement eigentlich immer ein Zeichen für suboptimales Klassendesign ist...erkläre doch mal, was in den anderen Fällen erfolgen soll, wenn also T kein Integer ist.

Bei einem
Delphi-Quellcode:
TNetGraph<Integer>
soll
Delphi-Quellcode:
GetItems(3)
also das 3. Element der Liste liefern.
Was soll bei einem
Delphi-Quellcode:
TNetGraph<String>
denn ein Aufruf von
Delphi-Quellcode:
GetItems('Foo')
liefern?

Harry Stahl 31. Jan 2015 16:27

AW: Generic Graph class
 
Wenn es denn sein muss, geht es auch mit case:

Delphi-Quellcode:
  case PTypeInfo(TypeInfo (T)).kind of
    tkInteger: ShowMessage ('Integer hier');
    tkFloat: ShowMessage ('Float hier');
    tkWString: ShowMessage ('String hier');
  end;
Wenn Du auf eingene Klassen oder Interfaces prüfen willst, musst Du eben auf tkClass oder tkInterface prüfen und dann noch mal näher unterscheiden, worum es sich genau handelt.

Die Info, was unter "kind" alles fällt, ist im TTypeKind in der Unit "System.TypInfo" beschrieben.

Stevie 1. Feb 2015 17:36

AW: Generic Graph class
 
Ab XE7 empfehle ich,
Delphi-Quellcode:
GetTypeKind(T)
zu nutzen. Das evaluiert der Compiler direkt und entfernt somit nicht ausgeführte Codepfade.

Harry Stahl 2. Feb 2015 20:53

AW: Generic Graph class
 
Liste der Anhänge anzeigen (Anzahl: 2)
Zitat:

Zitat von Stevie (Beitrag 1288481)
Ab XE7 empfehle ich,
Delphi-Quellcode:
GetTypeKind(T)
zu nutzen. Das evaluiert der Compiler direkt und entfernt somit nicht ausgeführte Codepfade.

In der Tat. Ich habe mir das mal im CPU-Fenster angesehen: Je nachdem, mit welchem Datentyp die Klasse TNetGraph instantiiert wird, hat der Compiler im Aufruf von "GetNetitem" bei GetTypeKind nur noch das Benötigte belassen und alles Überflüssige raus gemschmissen.

Anlage 1 zeigt den Source-Code und Anlage 2 die CPU zur Laufzeit bei Instantiierung der Klasse per "Integer". Der direkte Vergleich der 2 Abfragevarianten (Grün=GetTypeKind / Gelb=PTypeInfo) zeigt, dass man mit GetTypeKind erheblich Speicher einsparen kann.

Immerhin ein kleiner Trost für die Tatsache, dass die Verwendung von Generics im Allgemeinen zu Dopplungen des Speicherbedarfes führt (bei Instantiierung der Klasse mit unterschiedlichen Datentypen). Wobei natürlich auch weitere Vorteile von Generics "trösten", z.B. Fehler schon bei der Entwicklung auszumerzen und in gewissem Umfang auch Geschwindigkeitsoptimierungen erzielen zu können.

Guter Tipp!

himitsu 8. Feb 2015 03:11

AW: Generic Graph class
 
Zitat:

Zitat von Stevie (Beitrag 1288481)
Ab XE7 empfehle ich,
Delphi-Quellcode:
GetTypeKind(T)
zu nutzen. Das evaluiert der Compiler direkt und entfernt somit nicht ausgeführte Codepfade.

Genial, aber warum wissen weger OH noch DokWiki etwas davon?
Dort gibt es noch nichtmal die obligatorischen "Das ist Funktion Xyz in Unit Abc. Emba verfügt über keine Infos."-Einträge. :shock:

[add]
Noch genialer ist aber, was ich bisher aber noch nirgendwo in Google finden konnte, daß man Dieses sogar in den Conditional Expressions verwenden kann. :thumb:
Delphi-Quellcode:
{$IF GetTypeKind(TForm) in [tkClass, tkInterface]}
  ShowMessage('TForm ist eine Klasse/Interface');
{$ELSE}
  ShowMessage('TForm ist KEINE Klasse/Interface');
{$ENDIF}

{$IF GetTypeKind(Integer) in [tkClass, tkInterface]}
  ShowMessage('Integer ist eine Klasse/Interface');
{$ELSE}
  ShowMessage('Integer ist KEINE Klasse/Interface');
{$ENDIF}
Jetzt nur noch schauen, ob man das auch innerhalb der Generics nutzen kann, aber ich glaub nicht. :cry:

Stevie 8. Feb 2015 11:30

AW: Generic Graph class
 
Zitat:

Zitat von himitsu (Beitrag 1289189)
Jetzt nur noch schauen, ob man das auch innerhalb der Generics nutzen kann, aber ich glaub nicht. :cry:

Nö, kannste nicht, weil der Code innerhalb des Generics ist und dort T nicht bekannt ist. Und die Condition wird nicht jedesmal ausgewertet, also ist das leider wertlos.

himitsu 8. Feb 2015 13:10

AW: Generic Graph class
 
War schon fast klar, aber vielleich hätte man dort ja auch heimlich was verbessert haben können. (die Hoffnung stirbt zuletzt, aber sie stirbt ... oder wie man das immer so schön sagt)

Der Witz ist auch, daß im Interface das problemlos kompiliert und nicht gemeckert wird, daß man T noch nicht kennen würde, wobei das Ergebnis einfach nur False ist,
aber in der Implementation knallt die selbe Condition dann, von wegen "Konstante erwartet".


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:21 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz