Should I not pass an interface as const?

前端 未结 1 1857
抹茶落季
抹茶落季 2021-02-05 14:01

I recently came across (again) the Delphi compiler code-gen bug when passing an interface as const leaks a reference.

This happens if your method is declared to pass an

相关标签:
1条回答
  • 2021-02-05 14:13

    This happens if your method is declared to pass an interface variable as const, e.g.:

    procedure Frob(const Grob: IGrobber);
    

    That's not quite right. In order for there to be a leak, you need for there to be nothing in the code that ever takes a reference to the newly created object. So if you write:

    Frob(grob);
    

    There there's no problem because the interface grob already has at least one reference.

    The problem arises when you write:

    Frob(TGrobberImplementer.Create);
    

    In that scenario nothing takes a reference to the interface and so it is leaked. Well, it will be leaked so long as nothing in the implementation of Frob takes a reference to it.

    Have I done a bad thing?

    Well, that depends. I don't think anything particularly bad will come of what you have done. There is a downside in terms of performance because all of your functions that accept interface parameters will now have to add and release references, using implicit try/finally blocks. Only you can judge whether that matters.

    The more significant issue relates to code that is outside of your control. You give

    procedure OnDocumentComplete(Sender: TObject; const pDisp: IDispatch; var URL: OleVariant);
    

    as an example. There's no issue there because you never call that method. It's an event handler that you implement. The framework calls it, and it passes an interface that is already referenced.

    The real problem comes from methods declared in the RTL or any other third party code that you call. If you are calling the methods, and if they use const interface arguments then you can fall into the trap.

    It's easy enough to work around, albeit tiresome.

    grob := TGrobberImplementer.Create;
    Frob(grob);
    

    My reasoning to deal with the issue goes like this:

    1. There is a performance cost in passing interface parameters by value.
    2. I cannot ensure that every method that I call will accept interface parameters by value.
    3. Therefore, I embrace the fact that I need to deal with calling const interface parameters at least some of the time.
    4. Since I have to deal with it some of the time, and since I hate inconsistency, I choose to embrace dealing with it all of the time.
    5. Therefore, I choose to make all interface parameters in methods that I write be const.
    6. And consequently I make sure that I never pass an interface as an argument unless it is already referenced by a variable.
    0 讨论(0)
提交回复
热议问题