Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Warum sind Klassenoperatoren nicht bissl intelligenter? (https://www.delphipraxis.net/203663-warum-sind-klassenoperatoren-nicht-bissl-intelligenter.html)

himitsu 9. Mär 2020 17:56

Delphi-Version: 10.3 Rio

Warum sind Klassenoperatoren nicht bissl intelligenter?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Warum kann der Compiler nicht auch mal etwas Intelligenz zeigen und den impliziten Cast benutzen, anstatt beim
Delphi-Quellcode:
if List[0] = 0 then
aufzugeben?
Andersrum geht
Delphi-Quellcode:
if 0 = List[0] then
zum Glück auch nicht, obwohl der Compiler dort ja schon weiß, dass der Vergleich einen Integer ordinalen Typen haben möchte.
Delphi-Quellcode:
type
  TTestItem = record
  private
    FValue: Integer;
    function GetValue: Integer;
    procedure SetValue(const Value: Integer);
  public
    class operator Implicit(const Value: Integer): TTestItem; inline;
    class operator Implicit(const Value: TTestItem): Integer; inline;
    property RInt: Integer read GetValue;
    property WInt: Integer              write SetValue;
    property RWInt: Integer read GetValue write SetValue;
  end;

  TTestList = record
  private
    FItems: TArray<TTestItem>;
    function GetItem(DummyIndex: Integer): TTestItem;
    procedure SetItem(DummyIndex: Integer; const Value: TTestItem);
  public
    property Item[DummyIndex: Integer]: TTestItem read GetItem write SetItem; default;
  end;

procedure TForm1.FormCreate(Sender: TObject);
var
  List: TTestList;
begin
  List[0] := 123;                // Implicit:TTestItem > SetValue > SetItem

  List[0].WInt := 456;           // GetItem > SetValue > lost
  if List[0] <> 456 then lost;

  List[0].RWInt := 789;          // GetItem > SetValue > lost
  if List[0] <> 789 then lost;

//if List[0] = 0 then ;          // GetItem > Implicit:Integer > GetValue = [dcc32 Fehler] E2015 Operator ist auf diesen Operandentyp nicht anwendbar

  if Integer(List[0]) = 0 then ; // GetItem > Explicit > Implicit:Integer > GetValue

  if List[0].RInt = 0 then ;     // GetItem > GetValue

  if List[0].RWInt = 0 then ;    // GetItem > GetValue
end;
Oder hier einfach mal die Reihenfolge optimaler anpassen?
Delphi-Quellcode:
type
  TTest2 = record
  private
    FValue: Integer;
  public
    class operator Add (const LeftValue: TTest2; RightValue: Integer): Integer;
    class operator Equal(const LeftValue: TTest2; RightValue: Integer): Boolean;
    class operator Implicit(const Value: Integer): TTest2;
    class operator Implicit(const Value: TTest2): Integer;
  end;

procedure TForm1.FormCreate(Sender: TObject);
var
  X: TTest2;
begin
  if X = 0 then ; // Equal(Rec,Int)
  if 0 = X then ; // Implicit:Integer > Implicit:TTest2 > Equal(Rec,Int) ... erst rechts, dann links?
Klar, jetzt kann man natürlich auch noch alle möglichen Vergleichsoperatoren und alles auch nochmal umgedreht reinmachen, aber schlauer wäre es mit etwas mehr Intelligenz. :freak:

Und das mit den Settern läst sich dadurch verhindern, dass der Record keine Setter bekommt. (implizite Casts als Zuweisung funktionieren erstaunlicher Weise)

Andreas13 9. Mär 2020 18:00

AW: strunzdoofe Kassenoperatoren?
 
<gelöscht>: hat sich erledigt.

himitsu 9. Mär 2020 18:04

AW: strunzdoofe Kassenoperatoren?
 
glaub schon :roll:

Dennis07 9. Mär 2020 18:11

AW: strunzdoofe Klassenoperatoren?
 
Tut mir leid, aber ich checke dein Problem gerade nicht.
Der Equal-Klassenoperator funktioniert bei mir ohne Probleme in dieser Konstellation. Egal wie herum man die Operanden schreibt. Wenn du diesen aber nicht definierst, dann ist es natürlich klar, dass hier kein Vergleich möglich ist.
Kannst du evtl nochmal kurz erläutern, was dein Problem ist?

Was wirklich nicht funktioniert, egal, ob du den Impliziten Operator überlädst, ist, wenn du versuchst, einen Wert des Typs an eine Funktion zu übergeben. Das wäre durchaus mal einen Fix Wert.

Delphi-Quellcode:
procedure Poop(Arg: Integer);
begin
  //...
end;

begin
  Poop(List[0]); // Jeht nüscht
end.

himitsu 9. Mär 2020 18:43

AW: strunzdoofe Klassenoperatoren?
 
JA, WENN man diesen Operator einbaut.
Aber stell dir mal vor das wäre Intelligent und würde den ImplicitCast benutzen.

Und wierum hat einen großen Einfluss auf die Qualität des Vergleichs. (siehe TTest2)
In meinem Fall kann dieses Verhalten sogar einen Fehler erzeugen, wenn sich der Record nicht in einen Integer casten lässt.

Zitat:

Delphi-Quellcode:
Poop(List[0]);

Geht doch, denn hier wird natürlich der ImplicitCast verwendet.


Das hier ist noch ein einfaches Beispiel gewesen, welches ich als Test erstellt hatte.
Der originale Record, wo ich es verwenden wollte, würde jetzt bestimmt nochmal locker 100 weitere Operatoren benötigen, wenn ich dafür alle möglichen Konstellation in allen Richtungen reinmachen müsste.
Stattdessen bleibt mir wohl eher alles wegzuwerfen und eine weniger schöne Syntax zu verwenden, anstatt die paar Konvertierungen nur in den Record zu packen.

Dennis07 10. Mär 2020 03:57

AW: strunzdoofe Klassenoperatoren?
 
Ups, ja, das geht tatsächlich.

Aber es funktioniert nicht in jeder Konstellation. Bin ganz früher über das hier selbst gestolpert, als ich die Operatoren ausprobiert habe...

https://stackoverflow.com/questions/...hod-parameters

Das funktioniert nämlich nicht...

Daniel 10. Mär 2020 04:56

AW: strunzdoofe Klassenoperatoren?
 
Bitte gib Deinem Thema einen aussagekräftigen Titel ...

Rollo62 10. Mär 2020 08:52

AW: strunzdoofe Klassenoperatoren?
 
Zitat:

Zitat von himitsu (Beitrag 1459295)
Warum kann der Compiler nicht auch mal etwas Intelligenz zeigen und den impliziten Cast benutzen,

Das ist kein Problem, sondern ein Feature: die starke Typisierung bei Pascal :stupid:

himitsu 10. Mär 2020 11:07

AW: strunzdoofe Klassenoperatoren?
 
Es geht ja noch weiter ... Delphi/Pascal kennt keine Unterscheidung zwischen Bitwise und Logical, bei and/or/xor, aber du kannst beides Deklarieren (für das komische BCPP),
was erstmal nicht schlimm ist, wenn dir der Compiler eine Meldung geben würde, dass er das Andere nicht verwendet.

Oder wenn du Equal deklariert hast, dann könnte man das für NotEqual mitverwenden, wenn dieses nicht Deklariert wurde.
Oder warum nicht gleich "eine" CompareMethode für Alles? mit den drei Ergebnissen -1, 0 und 1 anstatt 6 Methoden. Delphi-Referenz durchsuchenCompareValue
Bzw. wenn etwas davon nicht deklariert wurde, dann könnte der Compiler mit 1 bis 2 Aufrufen alles Andere daraus generieren. (z.B. Equal und LessThan reicht aus, um alle Anderen zu emulieren)

Bei Add, And, Or und Xor ist die Reihenfolge der Parameter egal, also würde eine Variante reichen und der Compiler dreht die anderen Möglichkeiten einfach um.

Ich hatte mir auch ein
Delphi-Quellcode:
class operator In(const LeftValue: TTestItem; const RightValue: array of Integer): Integer;
deklariert, aber ist bei der Aufrufstelle was blöde.
Delphi-Quellcode:
// meldet mir out of Bonds, weil er das [] als Byte-Set interpretiert und erst dann die Typprüfung mit dem Ziel macht
if MyRec in [1000, 2000] then
// aber hier weiß er vom := , dass es ein IntegerArray werden soll, warum schaut er dann bei meinem Record nicht auch mal nach was er für Typen erwartet, schließlich wurde das vorher schon geparst
//Arr := [1000, 2000];

var Arr: TArray<Integer>;
if MyRec in Arr then // geht

Dennis07 10. Mär 2020 11:15

AW: Warum sind Klassenoperatoren nicht bissl intelligenter?
 
Jo, das mag unlogisch erscheinen. Ich denke allerdings, dass es halt nunmal ist, wie der Compiler intern die Operatoren verwaltet. Das Problem ist nunmal, dass
Delphi-Quellcode:
NotEqual
halt nicht in jedem Fall
Delphi-Quellcode:
not Equal
entspricht.
Eine Ungleichheit (oder eine Gleicheit) stellt man bei manchen Typen halt unterschiedlich fest, und ein generischer Vergleich wäre ja da nochmal etwas anderes (und auch nicht auf jeden Typen anwendbar, beispiel:

Delphi-Quellcode:
type
  TMyPoint = record
    X, Y: Integer;
end;
Jetzt stell da mal eine sinnvolle Deklaration für einen
Delphi-Quellcode:
Compare
-Operator auf... Geht nicht. Dennoch wären
Delphi-Quellcode:
Equal
,
Delphi-Quellcode:
NotEqual
,
Delphi-Quellcode:
GreaterThan
, ... problemlos möglich.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:18 Uhr.
Seite 1 von 2  1 2      

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