Autor Beitrag
sbdre
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Mi 03.11.10 15:06 
Hallo Delphi-Programmierer,

ich bin an folgendes Problem bei Funktionsaufrufen geraten.
Zunächst der Quellcode:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure MyTest(x : string ; b : boolean ; i : integer);
begin
  //inhalt egal
end;

MyTest(Null,Null,Null);


Der obige Code lässt sich compilieren, was ich sehr überraschend finde. D.h. Delphi (Delphi 2009) erkennt den Typkonflikt nicht.

Zur Laufzeit wird dann eine Exception ausgelöst:
"Variante des Typs (Null) konnte nicht in Typ (Integer) konvertiert werden"
[Delphi beginnt beim letzten Parameter, spielt aber keine Rolle]

Das Beispiel ist zwar trivial. Aber wir haben zahlreiche kombinierte Funktionsdefinitionen, wo gleichzeitig typisierte und Variant-Parametern vorkommen. Insofern liegt hier ein Risikopotential, wenn nicht ordentlich geprüft wird.

Kann man den Delphi-Compiler zu einer Prüfung schon während des compilierens veranlassen?

Vielen Dank im voraus
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 04.11.10 07:00 
user profile iconsbdre hat folgendes geschrieben Zum zitierten Posting springen:
Der obige Code lässt sich compilieren, was ich sehr überraschend finde. D.h. Delphi (Delphi 2009) erkennt den Typkonflikt nicht.
Es gibt auch keinen Typkonflikt. Der Typ ist Variant und damit passend. Der Inhalt (eben nichts) passt nicht. Inhalte prüft der Compiler aber normalerweise nicht (wie auch?).

Dass ein Null-Variant nicht umgewandelt werden kann, kann der Compiler so erst einmal nicht wissen. Natürlich ließe sich das über Compilermagic für diesen speziellen Typ lösen, aber wenn man diesen Null-Variant selbst angibt, dann kann Delphi wohl davon ausgehen, dass man das auch möchte.

Anders sieht es zur Laufzeit aus. Da kann ein Variant eben Null sein (Datenbankergebnis, ...) oder aus anderen Gründen nicht in den Zieltyp umwandelbar, deshalb wird das bei der Umwandlung geprüft.
sbdre Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Do 04.11.10 11:26 
Vielen Dank für die schnelle Antwort. Die Erklärung ist plausibel. Ich hatte insgeheim gehofft, dass es einen Compilerschalter gibt, der generell die Übergabe von Variant an typisierte Parameter unterbindet (und damit auch die Null).

Hintergrund der Frage: Wir haben zwei Funktionen zum Hinzufügen eines Datenbankfeldes per SQL, einmal kann ein Vorgabewert (DefaultValue) übergeben werden und einmal ein Berechnungsausdruck (DefaultExpression).

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
function addField( TableName:String
                   Fieldname:string;
                   FieldType:TFieldType;
                   Size:integer;
                   DefaultValue:Variant       // -- Vorgabe als Wert
                   ):integer;overloadvirtual;
function addField( TableName:String
                   Fieldname:string;
                   FieldType:TFieldType;
                   Size:integer;
                   DefaultExpression:String;  // -- Vorgabe als Berechnung
                   NotNull:boolean
                   ):integer;overloadvirtual;

Nun muss man natürlich höllisch aufpassen, wenn man auf einen Vorgabewert verzichtet. Bei der 1. Funktion übergibt man eine Null, bei der zweiten einen Leerstring. Übergibt man aus Versehen Null an die zweite Funktion kracht es.
Wäre halt schön gewesen, wenn der Compiler soetwas bereits beim Compilieren erkennt.
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6393
Erhaltene Danke: 147

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Do 04.11.10 15:15 
In dem Fall würde ich auch dort die Deklaration vom Typ Variant nehmen und innerhalb der Funktion prüfen, ob der Parameter den "richtigen" Typ zur weiteren Verarbeitung hat.

Also etwas so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function addField( TableName:String
                   Fieldname:string;
                   FieldType:TFieldType;
                   Size:integer;
                   DefaultExpression:Variant;  // -- Vorgabe als Berechnung
                   NotNull:boolean
                   ):integer;
begin
  if VarType(DefaultExpression) = varString then
    ...

end;

(ungeprüfter Source)
sbdre Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Do 04.11.10 15:33 
Das ist eine gute Idee und auf so etwas wird es nun hinauslaufen.
Fehler werden leider damit auch erst zur Laufzeit erkannt.