When I call Functions to get a value, I usually initialize varible, in case function fails or doesn't return anything and I want to avoid dealing with uninitialized variable. I do the same for string, integer or any other type.
Example for integer variables:
vPropValue := 0;
vPropValue := GetPropValue(vObject,'Height');
IF vPropValue > 0 Then
...
this it the most common how I use it.
I know I could use:
If GetPropValue(vObject,'Height') > 0 Then
...
but with first example I avoid multiple calls to function, if I need result again later in the code.
Same for string (even though i know local strings are initialized to empty string, while integers are not an can hold any value)
vName := '';
vName := GetObjectName(vObject,'ObjectName');
IF Trim(vPropStrValue) <> '' Then
...
I know I could take steps to avoid duplicate value assignment,like making sure Function returns 0 if everything fails. But I have 100s of functions and I can't rely I never made a mistake how functions handle everything and I'm sure some don't return 0, if everything fails.
I'm trying to understand why this is not desirable practice and how to best avoid it.
EDIT
Here is example where function doesn't return proper value or 0:
function GetValue(vType:integer):integer;
begin
if vType=1 then
Result:=100
else if (vType>2) and (vType<=9) then
Result:=200;
end;
procedure TForm1.Button1Click(Sender: TObject);
var vValue:integer;
begin
vValue:=GetValue(11);
Button1.Caption:=IntToStr(vValue);
end;
In this case the value returned from function is some random number.
In this case the initialization appears to be valid approach. OR NOT?
EDIT 2:
As David pointed out in his answer, correct, there was a warning
[dcc32 Warning] Unit1.pas(33): W1035 Return value of function 'GetValue' might be undefined
but, I ignored it, for no reason, just didn't look there. As it let me compile it, I thought it was OK. So, I did look for the warning and I 'fixed' quite a few functions that had similar issue, because of all IFs Result might not have been defined.
EDIT 3 & CONCLUSION:
I hope it adds to the scope of question and explanation:
Maybe an example of another twist that I use in most of my Functions, would also explain why I thought my initialization of variable was needed, is that I wasn't sure my Functions would behave correctly all the times, especially in case of nested function. Mots of them still are set like this:
function GetProperty(vType:integer):integer;
begin
Try
if vType = 99 then
Result:=GetDifferentProperty(vType)// <-- Call to another Function, that could return whatever...
else
begin
if vType=1 then
Result:=100
else if (vType>2) and (vType<=9) then
Result:=200;
end;
except
end;
end;
Now I'm addressing these Try Except End;
but some functions are 10 years old and to expect them to work 100%, based on my experience back then, is not something to rely on.
As the only developer on this project, I assume I should trust my functions (and he rest of my code), but I can't imagine in multiple developers environment that all function are set up properly.
So my conclusion: since I didn't take care of the basics - properly designed Functions, I need to have all these checks (variable initialization, Try Except
lines..) and probably some other unneccessary stuff.
StrToInt()
. To use them correctly, you are supposed to use atry/except
frame, where you handle the exception case. In the exception handler you could set the value after the function call (or do something completely different). Generally you should avoid this construction if there are alternatives. Code can be hard to read and exceptions can decrease performance. In the example given, alternatives likeStrToIntDef
orTryStrToInt
is to prefer. – SabbaticalvType=2
. You should make default value INSIDE the function like I described in my link above. See updated sample pastebin.ca/3272690 – Nuke