Delphi“Not”运算符返回错误

时间:2014-07-24 09:40:22

标签: delphi delphi-xe5

此代码用于解析编辑器是否应该是只读的。

Code Snippit

var
TempBool : Boolean;
begin
      TempBool := (fCurrentSelectedItem as TMyCustomObject).CanEdit; //Check whether this object can be edited; TempBool resolves to True
      TempBool := not(TempBool); // Toggle the Boolean value; !!-- TempBool still resolves to True
      curredtEach.properties.ReadOnly := TempBool; // Set the read only property on the editor
end;

TempBool解析为整数,如下所示

      // Integer(TempBool) = 0
      TempBool := (fCurrentSelectedItem as TMyCustomObject).CanEdit; 
      // Integer(TempBool) = -1
      TempBool := not(TempBool); 
      // Integer(TempBool) = -2     

找到这个link,但这没有帮助。

Delphi版本 - XE5

操作系统 - Windows 8.1

在第三方代码中进行挖掘后,我将这个示例放在一起,以演示如何复制问题。

program TestLongBool;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  System.Classes,
  System.Variants;

var
  Val: Boolean;
  Temp: Boolean;
  CanEdit: Boolean;

begin
  try
    Byte (Val) := 255;
    // Val resolves to  True | Integer(Val) = -1
    CanEdit := Val;
    // CanEdit resolves to True
    Temp := not CanEdit;
    // Temp is true when expected false | Integer(Temp) = -2
    if Temp then begin
      WriteLn ('Expected false');
    end;
    ReadLn;
  except
    on E: Exception do begin
      WriteLn (E.ClassName, ': ', E.Message);
      ReadLn;
    end;
  end;
end.

2 个答案:

答案 0 :(得分:9)

检查CanEdit是否以二进制方式返回正确的值,因为由于编译器的实现,不仅1被评估为True。但是当否定编译器生成xor $01时,除了1之外的任何正值仍会返回True。

您可以通过评估此表达式来完成此操作:Integer(TempBool)。如果这是除1以外的任何正值,那么CanEdit返回错误。

答案 1 :(得分:1)

总结:

错误(Boolean包含与01不同的整数值):

program Project9;

{$APPTYPE CONSOLE}

var B1, B3: Boolean;

begin
  ShortInt(B1):= -1;
  if B1 then Writeln('true')
        else Writeln('false');
  B3:= not B1;
  if B3 then Writeln('true')
        else Writeln('false');
  Readln;
end.

和快速解决方法(使用ByteBoolWordBoolLongBool):

program Project9;

{$APPTYPE CONSOLE}

var B1, B3: ByteBool;

begin
  ShortInt(B1):= -1;
  if B1 then Writeln('true')
        else Writeln('false');
  B3:= not B1;
  if B3 then Writeln('true')
        else Writeln('false');
  Readln;
end.