SITUATION
I am going to write a class and the constructor is a custom one that I have made because I need to initialize some values. This is the code I've written so far:
type
TCombinatorio = class(TObject)
private
valN, valK: integer;
result: double;
public
property K: integer read valK;
property N: integer read valN;
constructor Create(valN: integer; valK: integer);
end;
constructor TCombinatorio.Create(valN: Integer; valK: Integer);
begin
inherited Create;
Self.valN := valN;
Self.valK := valK;
if ((valN < 0) or (valK < 0)) then
begin
raise Exception.Create('N and K must be >= 0');
end;
end;
Since I am going to do some math calculations, I need to avoid negative numbers.
QUESTION
Can I raise an exception in the constructor in that way? I am running the code in this way:
procedure TForm1.Button1Click(Sender: TObject);
var a: TCombinatorio;
b: string;
begin
a := TCombinatorio.Create(5,-2);
try
//some code
finally
a.Free;
end;
end;
As you can see here I have wrong parameters for my constructor, since the second is negative. I also cannot understand (according with the code of my constructor) if the a.Free
inside the finally is really needed because when the constructor raises the exception, the destructor is called.
I thought to include the a := TCombinatorio.Create(5,-2);
inside the try-finally block to avoid the problem but I am not sure. What do you think?
Raise Exception. Create('Error happened'); Version 3 As for version 2, but overriding the address value of the exception. In all cases, when the raise call is made, code execution jumps to the Delphi exception handler - it either terminates the program, or uses the current Try statement to handle it.
A constructor is a special kind of method. If you call a constructor using a class reference, Delphi creates a new instance of that class, initializes the instance, and then calls the constructor proper. If you call a constructor using an object reference, Delphi calls the constructor as an ordinary method.
Your code is absolutely fine and correct. Raising exceptions from constructors is perfectly respectable. As you know the destructor is called.
You ask about this code:
a := TCombinatorio.Create(5,-2);
try
//some code
finally
a.Free;
end;
You are worried that Free
will be called after the object has already been destroyed. That cannot happen. If an exception is raised in the constructor then it propagates up the call stack. That happens before the try
block begins and so the finally
block does not execute. Indeed the assignment to a
does not happen.
Moving the creation inside the try
would be disastrous and is in fact an incredibly common mistake. Suppose you did that:
// WARNING THIS CODE IS DEFECTIVE
try
a := TCombinatorio.Create(5,-2);
//some code
finally
a.Free;
end;
Now if an exception is raised then Free
is called but on what? The variable a
is not initialized. Even if it was, which it isn't, that would still be a double free.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With