unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
function GetTrue: Boolean;
function GetValue1(var s: string): Variant;
function GetValue2(var s: string): Boolean;
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}{ TForm1 }function TForm1.GetTrue: Boolean;
begin
Result := True;
end;function TForm1.GetValue1(var s: string): Variant;
begin
Result := True;
s := 'World';
end;function TForm1.GetValue2(var s: string): Boolean;
begin
Result := True;
s := 'World';
end;procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
begin
if GetTrue or GetValue1(s) then
ShowMessage('Hello ' + s);
end;procedure TForm1.Button2Click(Sender: TObject);
var
s: string;
begin
if GetTrue or GetValue2(s) then
ShowMessage('Hello ' + s);
end;end.
//看看会Show什么出来?
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
function GetTrue: Boolean;
function GetValue1(var s: string): Variant;
function GetValue2(var s: string): Boolean;
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}{ TForm1 }function TForm1.GetTrue: Boolean;
begin
Result := True;
end;function TForm1.GetValue1(var s: string): Variant;
begin
Result := True;
s := 'World';
end;function TForm1.GetValue2(var s: string): Boolean;
begin
Result := True;
s := 'World';
end;procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
begin
if GetTrue or GetValue1(s) then
ShowMessage('Hello ' + s);
end;procedure TForm1.Button2Click(Sender: TObject);
var
s: string;
begin
if GetTrue or GetValue2(s) then
ShowMessage('Hello ' + s);
end;end.
//看看会Show什么出来?
难道不是
Hello
Hello
?
begin
Result := True;
ShowMessage('af');//加上这行再试试,会发现没有执行
s := 'World';
end;
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
function GetTrue: Boolean;
function GetValue1(var s: string): Variant;
function GetValue2(var s: string): Boolean; public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}function TForm1.GetTrue: Boolean;
begin
Result := True;
end;function TForm1.GetValue1(var s: string): Variant;
begin
s := 'World';
Result := True;end;function TForm1.GetValue2(var s: string): Boolean;
begin
Result := True;
s := 'World';
end;procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
begin
if GetTrue or GetValue1(s) then
ShowMessage('Hello ' + s);
end;procedure TForm1.Button2Click(Sender: TObject);
var
s: string;
begin
if GetValue2(s) or (GetTrue) then
ShowMessage('Hello ' + s);
end;
end.
這樣看下就不會錯了。 我不知道這算不算一個BUG,但對於程序來說這是可以避免的。 從優化的角度的來說是對的。只是碰上這個VAR 搞慘了。
的函數GetTrue 得到真後,就不執行GetValue2(s)了,第一個GetValue1(s)因為返回值是
Variant,編譯器不直接認為是布爾類型,所以執行了GetValue1(s)。
ˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍ
不知道大家認同不?
procedure TForm1.Button2Click(Sender: TObject);
var
s: string;
begin
if GetTrue or GetValue2(s) then //这个判断条件是'或',第一个GetTrue 条件满足,就不会再判断第二个了
ShowMessage('Hello ' + s);
end;
執行函數判斷,你可以跟一下匯編,從左到右去執行,第一個因為第二個是變體無法確定,所以優化不了。因為第二個二個都返回BOOL值,在OR的情況下優化是很正常的。 所以出現了上述的結果。看我上邊的代碼應該明白的。
begin
Result := True;//这句是执行了的
ShowMessage('af');//加上这行再试试,会发现没有执行
s := 'World';
end;
procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
begin
if GetTrue or Boolean(GetValue1(s)) then
ShowMessage('Hello ' + s);
end;procedure TForm1.Button2Click(Sender: TObject);
var
s: string;
begin
if GetTrue or Variant(GetValue2(s)) then
ShowMessage('Hello ' + s);
end;procedure TForm1.Button3Click(Sender: TObject);
var
s: string;
begin
{$B+}
if GetTrue or GetValue2(s) then
ShowMessage('Hello ' + s);
{$B-}
end;Bool条件判断优化($B-、$BOOLEVAL OFF)对Variant类型无效。
与工程的编译选项Complete boolean eval有关,打勾是一种结果;不打勾是另外一种结果。
这个选项控制的是对布尔值的运算是部分运算还是全部运算
我回家去试下
别出现生命BUG就行
procedure TForm1.Button2Click(Sender: TObject);
var
s: string;
begin
if GetValue2(s) or (GetTrue) then
ShowMessage('Hello ' + s);
end;
把GetValue2(s)放在前面,当然会运行,致使两次结果都是"Hello World",但是后面的GetTrue会被跳过,原理是一样的!
改成这样就都执行了:unit Unit1; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls; type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
function GetTrue: Boolean;
function GetValue1(var s: string): Variant;
function GetValue2(var s: string): Variant;
public
{ Public declarations }
end; var
Form1: TForm1; implementation {$R *.dfm} { TForm1 } function TForm1.GetTrue: Boolean;
begin
Result := True;
end; function TForm1.GetValue1(var s: string): Variant;
begin
Result := True;
s := 'World';
end; function TForm1.GetValue2(var s: string): Variant;
begin
Result := True;
s := 'World';
end; procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
begin
if GetTrue or GetValue1(s) then
ShowMessage('Hello ' + s);
end; procedure TForm1.Button2Click(Sender: TObject);
var
s: string;
begin
if GetTrue or GetValue2(s) then
ShowMessage('Hello ' + s);
end; end.
---------
这段代码运行的结果可能有两种:
与工程的编译选项Complete boolean eval有关,打勾是一种结果;不打勾是另外一种结果。
这个选项控制的是对布尔值的运算是部分运算还是全部运算
-------------
现代语言都是逻辑判断到能得出肯定结果就不会继续后面的表达式的计算了.因此那个函数可能会调用,
可能不会调用,看编译选项了.
这种表达式风格的代码,C用最多.
多个boolean用and连接 逐个判断到一个false就认定false而直接跳出
多个boolean用or连接 逐个判断到一个true就认定true而直接跳出
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls; type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
function GetTrue: Boolean;
function GetValue1(var s: string): Variant;
function GetValue2(var s: string): Variant;
public
{ Public declarations }
end; var
Form1: TForm1; implementation {$R *.dfm} { TForm1 } function TForm1.GetTrue: Boolean;
begin
Result := True;
end; function TForm1.GetValue1(var s: string): Variant;
begin
Result := True;
s := 'World';
end; function TForm1.GetValue2(var s: string): Variant;
begin
Result := True;
s := 'World';
end; procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
begin
if GetTrue or GetValue1(s) then
ShowMessage('Hello ' + s);
end; procedure TForm1.Button2Click(Sender: TObject);
var
s: string;
begin
if GetTrue or GetValue2(s) then
ShowMessage('Hello ' + s);
end; end.