![]() |
Interfaces in DotNet ganz anders?
Hi, ich arbeite mich gerade mit Delphi 2005 in DotNet ein und mir ist da etwas aufgestoßen.
Früher (in Win32) hat man interfaces üblicherweise ja so verwendet:
Code:
Dabei führte das nilen der Interfacereferenz zur Freigabe, es wurde also in diesem Fall das Destroy von TTest aufgerufen.
ITest = interface
procedure DoSomething; end; TTest = class(TInterfacedObject, ITest) public constructor Create; destructor Destroy; override; procedure DoSomething; end; var FTest: ITest; procedure InterfaceErzeugen; begin FTest := TTest.Create; FTest.DoSomething; end; procedure Interfacefreigeben; begin FTest := nil; end; Unter Delphi 2005 passiert das nicht. Das nilen nilt zwar die Interface-Referenz, der Destructor wird aber überhaupt nicht berührt. Ich habe jetzt schon Sachen wie
Code:
getestet und die haben anscheinend ohne Probleme funktioniert. Dabei ist doch gerade die Mischung von Object- und Interfacereferenzen das absolut böse "ohoh" in Delphi Win32.
var
FTest: TTest; procedure Irgendwas; begin FTest := TTest.Create; FTest.DoSomething; FTest.Free; end; Kann mich da mal jemand aufklären bitte? Bin sehr verwirrt. :cry: Vielen Dank schonmal. |
Re: Interfaces in DotNet ganz anders?
Ich hab mal was gelesen, dass das mit dem free'en was mit der Garbage Collection zu tun hat
|
Re: Interfaces in DotNet ganz anders?
Interfaces werden unter .NET durch den Garbage Collector verwaltet. Dieser räumt nur in unregelmäßigen Intervallen auf. D.h. Du kannst den Zeitpunkt nicht mehr direkt bestimmen. Muss wohl mal ein Tutorial her :mrgreen:
...:cat:... |
Re: Interfaces in DotNet ganz anders?
Hmm, es ist ja nicht so, daß ich davon noch nicht gehört hätte. Aber wenn dem so wäre müßte der Garbage Collector doch spätestens collecten, wenn die Applikation geschlossen wird. Da passiert aber gar nix.
Waaah, wie soll ich nur programmieren, wenn ich noch nicht mal Code bei der Freigabe eines Objektes ausführen kann? :wall: :cry: |
Re: Interfaces in DotNet ganz anders?
Nachtrag:
Nochmal von der anderen Seite. Normale Objekte kann ich doch auch explizit freigeben (Destroy, Disposable usw.). Das ist doch auch definitiv wichtig, wenn die z.B. die Freigabe eines Objekts andere Objekte über dessen Tod benachrichtigen soll (Bsp.: Katze, du brauchst keine Mäuse mehr jagen, die sind alle am Rattengift gestorben). Ich kann mir einfach nicht vorstellen, daß Interfaces hier derart aus der Rolle fallen. Das würde ihren Wert doch massiv schmälern. Vielleicht ist mein zweiter Ansatz (Mischung von Objekt- und Interfacereferenzen) doch naheliegender. Kann es sein, daß eine solche Herangehensweise jetzt erzwungen wird? Hmm, vielleicht kann ja noch jemand Licht in das Dunkel bringen. Auf jeden Fall schonmal vielen Dank. |
Re: Interfaces in DotNet ganz anders?
Du könntest versuchen mit
System.GC.Collect(); den Garbage Collector zu zwingen, aufzuräumen. Vielleicht wird Dein Destruktor ja dann aufgerufen. mfG mirage228 |
Re: Interfaces in DotNet ganz anders?
Zitat:
|
Re: Interfaces in DotNet ganz anders?
Zitat:
habe gleich noch einen :mrgreen: Habe ich in einem anderen Thread gefunden:
Delphi-Quellcode:
mit dem Kommentar "wenn es ganz haarig wird" :)
GC.WaitforPendingFinalizers();
Vielleicht hilft Dir das ja. mfG mirage228 |
Re: Interfaces in DotNet ganz anders?
Hallo,
Zitat:
Ich habe das erstemal am 17.05.2001 (musste ich im Regal jetzt ganz schnell suchen) mit .net zu tun gehabt und schon dort war klar: mit den .net E-Businesslösungen (so hies damals das 1st-Training) ist alles neu.... ohne Altlasten.... :-) thomas Sorry, normal bin ich nicht so schnell OT, aber hier kann ich es mir nicht verkneifen.... |
Re: Interfaces in DotNet ganz anders?
|
Re: Interfaces in DotNet ganz anders?
Zitat:
:) Danke für das Tutorial Sakura. Das klärt einiges auf und ich denke die Grundzüge verstanden zu haben. :) Nichtsdestotrotz wundern mich 3 Kleinigkeiten dabei: 1) Kann ich dem GC trauen? Mal ehrlich. Nehmen wir mal an ich habe ein Objekt auf das an einem spezifischen Punkt des Programms nicht mehr zugegriffen wird (z.B. alle Buttons, deren Klick eine Methode des Objekt aufrufen können, werden bis zum Neustart der Applikation disabled). Wie kann der GC solche Sachen auch nur ansatzweise nachvollziehen? Klappt sowas wirklich auch bei komplexeren Applikationen reibungslos? 2) Performance Ich mache hauptsächlich Multimedia-Anwendungen mit einer gehörigen Menge beweglicher Grafik. Insofern kann es manchmal zu nicht unerheblichen Performance-Einbrüchen kommen, wenn die Bilddaten nicht definiert und regelmäßig freigegeben werden, sondern sich der GC irgendwann mal dazu bequemt, diese Objkte freizugeben. 3) OO-Design Wie ich schon vorher erwähnte, gibt es doch viele Momente in denen die Freigabe eines Objekts andere Objekte darüber benachrichtigt, damit diese irgendein Verhalten ausführen können. Um das zu bewerkstelligen, müßte ich ja jetzt wieder den expliziten Destruktor-Aufruf erzwingen und das ist gerade nicht im Sinne von DotNet (wie ich deinem Tut entnehmen kann ;) ). Ist das jetzt schlechter OOP-Stil von mir oder kann man das Problem irgendwie andersweitig umgehen? Vielen Dank schonmal. :) |
Re: Interfaces in DotNet ganz anders?
"Thread titel Interfaces in DotNet ganz anders? Zitat:
Zitat:
Zitat:
Warum bin ich froh, dass Interfaces in .Net mit denen aus D32 nicht viel gemeinsam haben? Hast du schonmal versucht die Klasse hinter einer Interfaceinstanz abzufragen? Ich kenne nur dieses scheußliche Workaround. :?
Delphi-Quellcode:
type ISomeInterface = interface
procedure Allright(); procedure Hmmm(); // scheußliches Workaround :[ function ComparableInstance() :TObject; end; type TSomeImplementingClass = class(TInterfacedObject,ISomeInterface) public procedure Allright(); procedure Hmmm(); function ComparableInstance() :TObject; end; { TSomeImplementingClass } procedure TSomeImplementingClass.Allright(); begin Writeln('OK :thuimb:'); end; procedure TSomeImplementingClass.Hmmm(); begin Writeln(':gruebel: Hmmm...'); end; function TSomeImplementingClass.ComparableInstance(): TObject; begin Result := Self; end; var NewInstance :ISomeInterface; begin NewInstance := TSomeImplementingClass.Create(); if NewInstance.ComparableInstance() is TSomeImplementingClass then NewInstance.Allright() else NewInstance.Hmmm(); Sleep(3000); end. Da du in .Net die Referenzzählung nicht mehr selbst machen muss, sieht es auch gleich viel "aufgeräumter" aus. :mrgreen:
Code:
Du kannst wie gehabt den is-OIperator benutzen. (verhält sich schließlich wie eine Objektreferenz :) )
public interface ISomeInterface
{ void Allright(); void Hmmm(); } public class SomeImplementingClass : ISomeInterface { public void Allright() { Console.WriteLine("OK :thuimb:"); } public void Hmmm() { Console.WriteLine(":gruebel: Hmmm..."); } } internal class Program { private static void Main(string[] args) { ISomeInterface NewInstance = new SomeImplementingClass(); if (NewInstance is SomeImplementingClass) NewInstance.Allright(); else NewInstance.Hmmm(); Thread.Sleep(3000); } } } Edits: Schlechtschreibung... |
Re: Interfaces in DotNet ganz anders?
Hallo Sakura,
noch eine kleine Frage zu dem Tutorial. Wenn ich Destroy (free) weiterhin benutze. Heisst das, Destroy wird aufgerufen, die dortigen Anweisungen, wie das Freigeben von Resourcen (Bitmaps) wird ausgeführt. Ist dann das Objekt SELBER auch freigegeben oder nicht ? Ist das verhalten so wie früher oder wird das Objekt selber vom GC später irgendwann freigegeben ? |
Re: Interfaces in DotNet ganz anders?
Schritt für Schitt. Erst einmal Fingolfin...
Zitat:
Zitat:
Zitat:
Zitat:
Dann kannst Du das Objekt zwingen aufzuräumen und evtl. andere Objekte benarchichtigen. Unter .NET vergiss einfach, dass es einen Destructor gibt, der wird weder von der GC aufgerufen noch ist der den VBlern bekannt, die setzen alle auf Finalize/IDisposable. Mehr dazu in einem weiteren Tutorial dieser Tage. ...:cat:... |
Re: Interfaces in DotNet ganz anders?
Danke erstmal für die vielen Kommentare. :)
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
@Sakura Nutze... Danke für die Hinweise. Aber das ist genau der Knackpunkt den ich meine. Ich habe das Gefühl ab sofort mehr Arbeit darauf zu verwenden, darüber nachzudenken, ob ich denn nun irgendwas in irgendeiner Form freigeben werden kann/muß/soll, als früher, als ich prinzipell alles sofort nach dem Gebrauch gefreet habe. Der GC mag ja für viele Apps praktisch sein, aber im Arbeitsalltag kommen doch gerade diese kleinen "Sonderwünsche" andauernd vor. Ich möchte aber auch nicht zu negativ klingen. Im Allgemeinen gefällt mir DotNet ganz gut. Vielleicht fehlt mir einfach noch der technische Sachverstand, um die Vorteile des GC zu sehen. (Wenn jemand die vielleicht mal in einem Satz niederschreiben könnte, bezugnehmend auf meine Verwunderung, wäre ich überglücklich :) ). Danke auf jeden Fall für die Kommentare. :) |
Re: Interfaces in DotNet ganz anders?
Zitat:
Mit TInterfacedObject bekommst das Standardverhalten frei Haus. Aber wenn du dieses Objekt einmal als Interface benutzt kann es dir sehr schnell unter'm Hintern weggeklaut (==zerstört) werden. Wenn man _Release selbst implementiert kann man es verhindern, aber da sich die Instanz selbst verwalten muss kann es ganz schön haarsträubend ausarten. :? Zum Thema GC & Vertrauen: Die GC funktioniert normalerweise absolut prima, aber es gibt Grenzfälle...
Zitat:
So jetzt kann es die Mieze zerreißen. :zwinker: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz