whats new ¦  programming tips ¦  indy articles ¦  intraweb articles ¦  informations ¦  links ¦  interviews
 misc ¦  tutorials ¦  Add&Win Game

Tips (1541)

Database (90)
Files (137)
Forms (107)
Graphic (114)
IDE (21)
Indy (5)
Internet / LAN (130)
IntraWeb (0)
Math (76)
Misc (126)
Multimedia (45)
Objects/
ActiveX (51)

OpenTools API (3)
Printing (35)
Strings (83)
System (266)
VCL (242)

Top15

Tips sort by
component


Search Tip

Add new Tip

Add&Win Game

Advertising

91 Visitors Online


 
...use Interfaces and TInterfaceList?
Autor: twm
[ Print tip ]  

Tip Rating (31):  
     


{
  The Classes unit provides a class TInterfaceList which is a TList that can store
  interfaces (yes, those that are descendants of IUnknonw). If you need to store
  interfaces do not use a TList, use TInterfaceList, otherwise you will run into
  trouble.

  Here is how to do it:
}

type
  
IMyInterface = interface
    procedure 
AMethod;
  end;

type
  
TMyObject = class(TInterfacedObject, IMyInterface)
    procedure AMethod;
  end;

  {....}

var
  
InterfaceList: TInterfaceList;
  MyInt: IMyInterface;

  {....}
  
MyInt := TMyObject.Create;
  InterfaceList.Add(MyInt);
  
  {....}

  
MyInt := IMyInterface(InterfaceList[Index]);
  MyInt.AMethod;

  {Easy, but there is a catch. The following code will crash: }

  {... declarations like above ...}
  
InterfaceList.Add(TMyObject.Create);
  MyInt := IMyInterface(InterfaceList[0]);
  MyInt.AMethod; // -> Access Violation

{
  Why is that? That is because instead of storing the IMyInterface if TMyObject we
  stored its IUnknown interface in the InterfaceList. Retrieving this resulted in an
  invalid typecast of a non-IMyInterface interface to IMyInterface. The resulting
  interface pointer pointed to a IUnknown interface which simply does not have the
  AMethod method. When we tried to call this method, the code tried to get the
  corresponding method pointer from the interface's VMT and got some garbage instead.

  The following, minimally changed code works:
}

  {... declarations like above ...}
  
InterfaceList.Add(IMyInterface(TMyObject.Create));
  MyInt := IMyInterface(InterfaceList[0]);
  MyInt.AMethod; // -> Access Violation
  
{
  That is, because the explicit typecast to IMyInterface before adding the TMyObject
  object to the list returned the IMyInterface interface of TMyObject rather than
  the IUnknown interface. But since IMyInterface is a descendant interface of
  IUnknown, it can still be stored in the InterfaceList.

  Confused? Yes, so was I. It took me ages to figure out what was wrong with my
  program that crashed unexpectedly. I hope this will help others to avaoid this
  problem or at least find the reason why their programs don't behave as they should.
}


 

Rate this tip:

poor
very good


Copyright © by SwissDelphiCenter.ch
All trademarks are the sole property of their respective owners