2014-03-07 40 views
6

初始化我有一个类如何对象在德尔福XE VS XE4

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

在我在堆栈创建的类的对象

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; 

我没有经过任何的功能之一在aMsg中如此理想选项没有设置。

在德尔福XE默认情况下选项设置为零,所以这个DoRefresh不会被调用,但是当我在Delpi XE4中执行相同的代码时,选项用一些随机值进行初始化,并且AutoSearch总是变为真,并且它导致调用这个DoRefresh功能是不受欢迎的。

我想知道是否有任何编译器选项将默认值设置为未初始化的变量。我作为目前唯一的解决办法是这样的

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; 

这是一个正确的方式?

+1

什么是MyMsg?这是一堂课,记录还是什么?你说默认值,但这个参数在你的情况下没有默认值。你如何分配默认值? – Darthman

+2

编译器没有警告你有关该代码?它应该告诉你'选项'是未初始化的。切勿忽略编译器警告。 –

+1

你接受了解决问题的最佳答案,但实际上并没有回答你问的问题。你询问了一个局部变量的初始化。 –

回答

7

由于其他答案已经说过局部变量没有初始化。 但是我想在这里添加的是as是无效的。这意味着你不需要检查是否分配了aMsg.OptionalObject。你可以这样写:

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

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

请记住,它会抛出一个异常,如果OptionalObject不从TLoadOption继承。代码看起来总是如此。因此,如果您确定可以使用硬件:

begin 
    if Assigned(aMsg.OptionalObject) and TLoadOption(aMsg.OptionalObject).AutoSearch then 
    DoRefresh; 
end; 
6

否。假设TLoadOption是一个对象(非托管引用类型),您必须自己初始化局部变量。没有选择让他们为你初始化。未初始化的引用类型(除了托管类型,如字符串等)的局部变量将始终包含堆栈中该位置的任何垃圾数据。这使得使用Assigned不可能。

您可能只是简化了一下代码,但是这样做的时间可以尽可能短。

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

Options是非托管类型的局部变量。这意味着它没有被初始化。它可以有任何价值,直到你初始化它。如果变量有时恰好具有值nil而没有初始化它,那么这对你来说就不太合适。

您必须在尝试读取本地变量之前初始化本地变量。

+0

感谢您的回答,但我很好奇它如何在XE中始终正常工作? – Jeeva

+1

@Jeeva他回答说 - 你真幸运。最有可能的解释是,调用函数(或某个以前的函数)半可靠地在堆栈上留下了一些更高的内容(变量结束了),从而使代码正常工作 - 现在已经发生了某种变化。 –

+3

@J ...其实,他很倒霉,以前它工作过! ;-) –

1

根本不需要本地变量。

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

确实如此。但由此产生的代码并不令人愉快。 –

+0

1.您不需要本地变种。 2.你不需要初始化它。 3.如果OptionalObject不从TLoadOption继承,则不会中断。至于我这个代码是合乎逻辑的。 –

+0

本地变量很好。它使代码更好。它可以让你避免像你一样重复自己。 –