2014-03-07 12 views
6

IWie Objekte werden in delphi XE vs XE4 initialisiert

type 
    TLoadOption = class 
    private 
    FAutoSearch: Boolean; 
    public 
    property AutoSearch: Boolean read FAutoSearch write FAutoSearch; 
    end; 

In einer der Funktionen i Erstellung ist das Objekt der Klasse in Stapel

procedure MyView.InitializeForm(const aMsg: MyMsg); 
//--------------------------------------------------------------------------- 
var 
    Options: TLoadOption; 
begin 

    if aMsg.OptionalObject <> nil then 
    Options := aMsg.OptionalObject as TLoadOption; 

    if Assigned(Options) and Options.AutoSearch then 
    DoRefresh; 
end; 

ich vorbei bin nicht etwas eine Klasse in aMsg sind also idealerweise keine Optionen eingestellt. In Delphi XE werden die Optionen standardmäßig als nil gesetzt und daher wird dieser DoRefresh nicht aufgerufen, aber wenn ich denselben Code in Delpi XE4 ausführe, werden die Optionen mit einem zufälligen Wert initialisiert und AutoSearch wird immer wahr und es ruft auf DoRefresh-Funktion, die unerwünscht ist.

Ich frage mich, ob es Compiler-Optionen gibt, die Standardwerte auf nicht initialisierte Variable setzen. Meine einzige Lösung im Moment ist so

procedure MyView.InitializeForm(const aMsg: MyMsg); 
    //--------------------------------------------------------------------------- 
    var 
     Options: TLoadOption; 
    begin 
     Options := nil; 

     if aMsg.OptionalObject <> nil then 
     Options := aMsg.OptionalObject as TLoadOption; 

     if Assigned(Options) and Options.AutoSearch then 
     DoRefresh; 
    end; 

ist das ein richtiger Weg?

+1

Was ist MyMsg? Dies ist eine Klasse, aufnehmen oder was? Sie sagen über den Standardwert, aber dieser Parameter hat in Ihrem Fall keinen Standardwert. Wie weisen Sie den Standardwert zu? – Darthman

+2

Hat Sie der Compiler nicht vor diesem Code gewarnt? Es hätte dir sagen sollen, dass 'Optionen' nicht initialisiert wurde. Ignoriere niemals eine Compiler-Warnung. –

+1

Sie haben die Antwort angenommen, die die beste Lösung für Ihr Problem ergab, aber auch die Frage, die Sie gestellt haben, nicht beantwortet. Sie haben nach der Initialisierung einer lokalen Variablen gefragt. –

Antwort

7

Wie die anderen Antworten bereits gesagt, ist die lokale Variable nicht initialisiert. Aber was ich hier hinzufügen möchte ist, dass as ist nicht sicher. Das bedeutet, dass Sie nicht überprüfen müssen, ob aMsg.OptionalObject zugewiesen ist. Sie können einfach schreiben:

var 
    Options: TLoadOption; 
begin 
    Options := aMsg.OptionalObject as TLoadOption; 

    if Assigned(Options) and Options.AutoSearch then 
    DoRefresh; 
end; 

Beachten Sie, dass es eine Ausnahme auslösen, wenn OptionalObject von TLoadOption erbt nicht. Der Code sieht so aus, als sei das immer der Fall.Wenn Sie also sicher sind, dass Sie einen Hardcast verwenden können:

6

Nein. Unter der Annahme, dass TLoadOption ein Objekt (nicht verwalteter Referenztyp) ist, müssen Sie lokale Variablen selbst initialisieren. Es gibt keine Option, sie für Sie initialisieren zu lassen. Lokale Variablen für Referenztypen (mit Ausnahme von verwalteten Typen wie Strings usw.), die nicht initialisiert sind, enthalten immer die Daten, die an diesem Speicherort im Stapel vorhanden waren. Dies macht Assigned unmöglich.

Sie könnten Ihren Code ein wenig vereinfachen, aber das ist so kurz wie es nur geht.

var 
    Options: TLoadOption; 
begin 
    if aMsg.OptionalObject <> nil then begin 
    Options := aMsg.OptionalObject as TLoadOption; 
    if Options.AutoSearch then DoRefresh; 
    end; 
end; 
11

Eine lokale Klasse ist nicht initialisiert. Sie müssen es auf Null setzen, bevor Sie seine Zuweisung testen.

Siehe Are delphi variables initialized with a value by default?.

Nur lokale Referenzzähler werden initialisiert (Beispiel: String, dynamische Arrays, Interface, Varianten).

Wenn Sie auf mobile Plattformen zielen, bei denen ARC (automatische Referenzzählung) eingeführt wird, werden Klassen jedoch als Referenz gezählt. Siehe Automatic Reference Counting in Delphi Mobile Compilers.

3

Options ist eine lokale Variable eines nicht verwalteten Typs. Was bedeutet, dass es nicht initialisiert ist. Es kann einen beliebigen Wert haben, bis Sie es initialisieren. Wenn die Variable manchmal den Wert nil hat, ohne dass Sie sie initialisiert haben, dann ist das einfach Pech für Sie.

Sie müssen lokale Variablen initialisieren, bevor Sie versuchen, sie zu lesen.

+0

Vielen Dank für Ihre Antwort, aber ich bin neugierig auf Wie funktioniert es immer in XE? – Jeeva

+1

@Jeeva Er antwortete das - du hattest Glück. Die wahrscheinlichste Erklärung ist, dass die aufrufende Funktion (oder eine vorhergehende Funktion) halb-zuverlässig etwas höher auf dem Stapel (wo Ihre Variable gelandet ist) gelassen hat, was den Code funktionierte - und jetzt hat sich das irgendwie geändert. –

+3

@J ... Eigentlich hatte er Pech, dass es vorher geklappt hat! ;-) –

1

Sie benötigen keine lokalen Var überhaupt.

procedure MyView.InitializeForm(const aMsg: MyMsg); 
begin 
    if Assigned(aMsg.OptionalObject) 
    and (aMsg.OptionalObject is TLoadOption) 
    and (aMsg.OptionalObject as TLoadOption).AutoSearch 
    then 
    DoRefresh; 
end; 
+0

True. Aber der resultierende Code ist nicht angenehm. –

+0

1. Sie benötigen keine lokalen var. 2. Sie müssen es nicht initialisieren. 3. Wenn optionalObject nicht von TLoadOption erbt, bricht nichts ab. 4. Für mich ist dieser Code logisch. –

+0

Die lokale var ist gut. Es macht den Code besser. Sie können vermeiden, sich immer wieder zu wiederholen. –

Verwandte Themen