I'm having problems with Delphi 10.2 Berlin Update 2 and tDSRestconnection by receiving tStream from Rest Server ... but not always:
I'm having problems with Delphi 10.2 Berlin Update 2 and tDSRestconnection by receiving tStream from Rest Server ... but not always:
function getfilefromserver(vFileId:longint; vFilePassword:string; vDestinationFileName:string):int64;
var
vData:tStream;
vFile:tFileStream;
begin
result:=0;
try
vFile:=tFileStream.create(vDestinationFileName, fmCreate);
vData:=
fClientModule.directfilereceive_byId_v2(vFileId, vFilePassword);
vfile.CopyFrom(vdata, 0);
result:=vfile.size;
finally
if assigned(vfile) then begin
vfile.free;
vfile:=nil;
end;
if assigned(vdata) then begin
vdata.free;
vdata:=nil;
end;
end;
end;
The Problem is, that vDATA is shown sometimes in Debugger as vDATA = () and in that case i get an exception, but most of the time the vdata has properties like .size etc and is working. Is this a bug in newest Delphi or i'm doing something wrong with tStream and Rest ?
function getfilefromserver(vFileId:longint; vFilePassword:string; vDestinationFileName:string):int64;
var
vData:tStream;
vFile:tFileStream;
begin
result:=0;
try
vFile:=tFileStream.create(vDestinationFileName, fmCreate);
vData:=
fClientModule.directfilereceive_byId_v2(vFileId, vFilePassword);
vfile.CopyFrom(vdata, 0);
result:=vfile.size;
finally
if assigned(vfile) then begin
vfile.free;
vfile:=nil;
end;
if assigned(vdata) then begin
vdata.free;
vdata:=nil;
end;
end;
end;
The Problem is, that vDATA is shown sometimes in Debugger as vDATA = () and in that case i get an exception, but most of the time the vdata has properties like .size etc and is working. Is this a bug in newest Delphi or i'm doing something wrong with tStream and Rest ?
You might find this post useful:
ReplyDeletehttp://stackoverflow.com/questions/8548843/why-should-i-not-use-if-assigned-before-using-or-freeing-things/8550628#8550628
Yusuf Zorlu Initializing the object to nil would be a pointless waste of time. This is the pattern:
ReplyDeleteobj := TMyObject.Create;
try
obj.DoSomething;
finally
obj.Free;
end;
You prefer:
obj := nil;
try
obj := TMyObject.Create;
obj.DoSomething;
finally
obj.Free;
end;
I'm assuming that you are happy to remove the pointless test for obj being assigned.
Sure you can do that but it's an extra line of code, it's not idiomatic, and it only works for resource acquisition by way of assignment.
Consider this pattern:
lock.Enter;
try
DoSomething;
finally
lock.Leave;
end;
You have to write it that way because you must only call Leave if Enter succeeded.
The pattern in pseudo code, that works for all forms of resource management using try/finally, is:
AcquireResource;
try
UseResource;
finally
ReleaseResource;
end;
There is just one scenario where it can be useful to initialise to nil. That's when you want to avoid deep nesting, or perhaps have optional instantiation. For instance, instead of:
obj1 := TMyObject.Create;
try
obj2 := TMyObject.Create;
try
obj3 := TMyObject.Create;
try
obj1.DoSomething;
obj2.DoSomething;
obj3.DoSomething;
finally
obj3.Free;
end;
finally
obj2.Free;
end;
finally
obj1.Free;
end;
you might prefer:
obj1 := nil;
obj2 := nil;
obj3 := nil;
try
obj1 := TMyObject.Create;
obj2 := TMyObject.Create;
obj3 := TMyObject.Create;
obj1.DoSomething;
obj2.DoSomething;
obj3.DoSomething;
finally
obj3.Free;
obj2.Free;
obj1.Free;
end;
You can make an argument for that sometimes. For the code in your original question, that's not so, and you should write it the way I said.
Thanks for your good informations. Will give my best to write it this way from now on ;-)
ReplyDelete