views:

196

answers:

5

I am a Delphi programmer and trying to get some stuff done with C# here. Does interfaces in C# works in the same way as in Delphi - you don't need to worry in freeing it as it is freed when its out of scope.

A: 

Everything in c# is garbage collected, so you do not need to free them manually.

But there are significant differences. Delphi interfaces are reference counted, c# interfaces are garbage collected. C# supports multiple interface inheritance.

Gabe Moothart
Delphi also supports multiple interface inheritance, no diff there.
Henk Holterman
Surely it's true only to say that both C# and Delphi support multiple interface *implementations*? "Multiple interface inheritance" might suggest that an interface "A" may inherit from multiple interfaces, "B" and "C" which is *not* possible in either Delphi or C#. Of course, if a class implements multiple interfaces then any derived/descendant classes "inherit" those multiple interfaces, but to my mind that is an incidental side effect of having implementation inheritance and the ability to implement multiple interfaces, and does not constitute a multiple interface inheritance "feature".
Deltics
@Deltics, see this for starters: http://stackoverflow.com/questions/2346210/
Henk Holterman
@Deltics: Note that `interface IFoo : IBar, IDisposable` is OK, but when you reflector it back a class implementing IFoo might show up with the 3 interfaces, unrelated .
Henk Holterman
@Henk: Thanks for that link. Seems like pointless syntactic sugar to me... "inheriting" from multiple interfaces is semantically and functionally equivalent to requiring that multiple interfaces be implemented (if one designated "multiple derived" interface is implemented). i.e. it's a useful way of implementing an interface contract, but it's not "inheritance" in the way that it is usually meant in OO, and your reflector observations would seem to confirm that - it's syntactic sugar that "looks like" inheritance, but isn't really. At least, not imho.
Deltics
@Deltics: I disagree, it makes sense. Like in `IFoo f = ...; Ibar b = f;` Every IFoo IS-A IBar. Substitution principle working.
Henk Holterman
Well, the accepted answer to the SO question you linked to says not: "An interface derivation relationship doesn't imply that at all" ... ""interface inheritance does not mean "this is a kind of that", but rather "every implementation of this is required to also implement that"". <shrug>
Deltics
I know and I disagree.
Henk Holterman
+7  A: 

Yes, to a programmer they look the same. Use And Forget.

Internally they work different, in .NET an interface is (just another) reference that is sweeped by the Garbage collector.

In Delphi interfaces are a special kind of reference that are reference-counted (a different Meory management technique).

The main .NET/Delphi difference is that in .NET all references (interface, object and array) are garbage Collected.

Henk Holterman
Thanks for the explanation. Would be a valid point to say that if I make my object implement IDisposable and use something like "using (MyClass myobj = new MyClass()){} I could achieve something similar to what Delphi does (out of scope, you're done) rather than wait for the garbage collector?
Ronaldo Junior
@Ronaldo: Yes, somewhat. But you should not normally do that. IDisposable is for managing resources (FileHandles), not memory. You cannot control the lifetime of objects, but you don't have to worry about it either.
Henk Holterman
+2  A: 

I don't think it is freed when out of scope but when the garbage collection happens (when they are not used anymore)

François
actually correct but hard to decipher: what behaviour is Delphi and what .NET?
Henk Holterman
A: 

Memory management is handled by the CLR. Garbage collection is an intrinsic service in the CLR.

You do not need to null out variables or fields in order to have the object collected by garbage collection.

You do not need to implement or use IDisposable to clean up memory. The Dispose method does nothing to free managed objects in memory. The Dispose method is should be used to free up "unmanaged" resources including database connections, bitmaps, or any unmanaged structures you may be holding onto.

If you are talking about interfaces as in visual components (Forms, dialogs, etc), this gets a little bit more confusing. In WinForms, I believe that when an interface (visual) is no longer visible, it will be cleaned up and garbage collected. The form will be recreated again when it is needed. In WPF, Windows and Pages are not immediately destroyed. They are cached for the lifetime of the application unless they are specifically cleaned up by the application developer. This improves performance with WPF applications but places an additional burden of having to worry about resources in your application.

Garbage collection is a completely separate topic. The actual freeing of managed objects from physical memory occurs in here and is completely up to the Garbage Collection service and you should not normally have to worry about how this works.

Cheers

Dave White
-1 for the "you do not need to null out ..." phrase. True for variables, dangerously false for fields.
Henk Holterman
For the rest this is lacking any Delph perspective.
Henk Holterman
When the class goes out of scope, the fields are cleaned up. Why would you need to null out fields? If your class is holding onto unmanaged resources, you need to clean those up in your Dispose method implementation. Nulling out the field doesn't necessarily clean up unmanaged resources.The question was also about memory management in C#. I was missing the explicit link between Delphi interface and C# interface, but didn't feel it detracted from my contribution.
Dave White
You may need to null out fields holding references to objects for the objects to become collectable. I see your other interpretation now but that makes no sense - no language makes you clean out var/fields. And interfaces contain neither
Henk Holterman
+8  A: 

The key difference between Delphi and .NET in this area, relating specifically to interfaces, is the non-deterministic nature of the clean-up.

In Delphi all interface usage follows the COM model. That is, it is reference counted. If the class implements a reference counted lifetime management model, then when the reference count drops to zero the object instance is destroyed AT THAT POINT.

NOTE: Lifetime management is a function of the class implementation. To see this most clearly, a look at the implementation of IUnknown.Release in TInterfacedObject:

function TInterfacedObject._Release: Integer;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then
    Destroy;
end;

If the implementation of Release did not call Destroy, then the object would NOT be destroyed when the reference count drops to zero and would still have to be explicitly Free'd through some object reference to the object. This can be used in Delphi to create objects which implement interfaces but which are not subject to automatic, reference counted lifetime management (though you cannot avoid the reference counting code injected by the compiler, i.e. calls to AddRef and Release).

In .NET first of all there is no reference counting per se. The Garbage Collector works in a far more sophisticated fashion, the details of which are not directly relevant to this discussion.

The key difference is that when an object is no longer being used (however that is determined beyond a simple reference count) that is NOT the point at which it is destroyed in .NET.

In fact, it is theoretically possible that unused objects would accumulate in your application until a much, much later point in your process lifetime - especially in compute intensive applications with few idle cycles. In .NET you simply cannot be sure precisely when those unused objects will eventually be free'd.

Some would argue that this is A Good Thing, though it confuses the usual practice of cleaning up resources that are locked or owned by objects when those objects are destroyed, since you typically need to release those locked/owned resources more urgently than is afforded by waiting around for the Garbage Collector. This is where IDisposable comes in in .NET, the details of which are again not directly relevant can may be researched further at your leisure.

Deltics
Thanks for the great explanation - your answer and Henk's one helped me a lot.
Ronaldo Junior