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 ?

Comments

  1. Yusuf Zorlu Initializing the object to nil would be a pointless waste of time. This is the pattern:

    obj := 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.

    ReplyDelete
  2. Thanks for your good informations. Will give my best to write it this way from now on ;-)

    ReplyDelete

Post a Comment