A "D'oh" moment for me is when I do an obvious coding error but I am not able to see it even in the debugger.
Consider the following section of code:
Would you expect to see the message "String list is empty"? I would. We have only created the string list and just after creating, it should be empty (i.e. the Count property should not be greater than zero).
var
sl : TStringList;
begin
sl := TStringList.Create;
try
if (NOT sl.Count > 0) then ShowMessage('String list is empty');
finally
FreeAndNil(sl);
end;
end;
However the message does not get displayed :(
Of course, in my real-world code the entire boolean expression was much more complicated containing several AND'd and OR'd parts.
Now, why the "(NOT sl.Count > 0)" evaluates to false (when the Count IS 0)?
Welcome to the traps of negative boolean expression + bitwise operations on integers!
Yes, I could have written the expression as "(sl.Count = 0)", but alas, it was written as it was with "(NOT sl.Count > 0)".
To fix my error, the correct expression should have been (note the extra parentheses) :
if (NOT (sl.Count > 0)) then ShowMessage('String list is empty');
Now, about the "d'oh" :
The original "(NOT sl.Count > 0)" evaluated to false as
- sl.Count is 0,
- "NOT 0", since "0" is an integer, evaluates as a bitwise expression and returns -1,
- "-1" is NOT greater than 0, thus the final false result of my wrong expression!
Each day I learn something I already knew :) You?
Related:


This can’t be fixed. Becaus then some expressions ‘ll evaluate wrong(which need NOT first).
You wrote: “Of course, in my real-world code the entire boolean expression was much more complicated containing several AND’d and OR’d parts.”
Well, for me it seems that this was the real problem: the if expression was too complicated to have a quick overview.
If I combine multiple conditions in one if expression, I always set brackets everywhere even if they are not neccessary. Just to have clean code that everybody can read easily later. And if there are more than very few conditions, I put them in well named variables and use these inside the if expression.
So I never ran into this issue, but of course I am aware of it.
@Sebastian, the real-world expression contained several well bracketed parts (readable), then I added “(NOT sl.Count > 0)” and it stopped working. Happens.
var programmersPain: Extended;
begin
programmersPain :=
AbsDistance(
intendedFunction,
actualFunction) * (1 / Max(NumHoursTillDeadline, 0.001));
end;
// Note, the constant 0.001 was added to the Max() function in the denominator because once the number of hours left on the project is less than 1, the programmer’s pain approaches infinity asymptotically. And to avoid a divide by zero Exception of course.
One of the reasons I like Delphi in my bigger projects.
When I use C I sometimes forget to use == for the equivilance. I found a bug recently from a 7 year old program I wrote
if (ErrLevel=0) // no error so continue
{
…
}
needless to say my ErrLevel was alway 0 and the condition always true
As far as I know the combination “if not” is only used when you are specifying booleand variables as conditions. This enalbes you to write “if MyBoolVar true then” easier as just “if not MyBoolVar then”. Both off theese examples excutes code when MyBoolVar is false.