AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Interfaces in DotNet ganz anders?

Ein Thema von Fingolfin · begonnen am 1. Dez 2004 · letzter Beitrag vom 4. Dez 2004
Antwort Antwort
Seite 2 von 2     12   
Fingolfin

Registriert seit: 7. Okt 2003
62 Beiträge
 
#11

Re: Interfaces in DotNet ganz anders?

  Alt 2. Dez 2004, 20:18
Zitat:
Zitat:
Hier scheint was sehr grundlegend anders als bei Win32 zu laufen. Und ich dachte DotNet mal 2-3 Stunden angucken und gut.
DER war richtig gut, da fängt der Arbeitstag mit einem richtigen Schmunzeln an Spin.
Ich glaube, ich hätte besser den hinmachen sollen:


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.
  Mit Zitat antworten Zitat
Robert_G
(Gast)

n/a Beiträge
 
#12

Re: Interfaces in DotNet ganz anders?

  Alt 2. Dez 2004, 21:29
"Thread titel
Interfaces in DotNet ganz anders?
Zum Glück auch.

Zitat von Fingolfin:
1) Kann ich dem GC trauen?
Solange du nicht wie ein VB'ler wild drauf los erzeugst ist alles in Butter.

Zitat von Fingolfin:
2) PerformanceIch 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.
Und du bist dir sicher, dass du da mit D32 besser dran warst? In Delphi32 gibt es einen messbaren Performance hit bei der Verwendung von Interfaces. Außerdem

Zitat von Fingolfin:
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.
Was hindert dich daran einen Event im Finalizer oder in der Dispose zu feuern?


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.
Code:
   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);
      }
   }
}
Du kannst wie gehabt den is-OIperator benutzen. (verhält sich schließlich wie eine Objektreferenz )

Edits: Schlechtschreibung...
  Mit Zitat antworten Zitat
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#13

Re: Interfaces in DotNet ganz anders?

  Alt 3. Dez 2004, 02:37
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 ?
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: München
11.412 Beiträge
 
Delphi 11 Alexandria
 
#14

Re: Interfaces in DotNet ganz anders?

  Alt 3. Dez 2004, 09:33
Schritt für Schitt. Erst einmal Fingolfin...

Zitat von Fingolfin:
1) Kann ich dem GC trauen?
Ja

Zitat von Fingolfin:
z.B. alle Buttons, deren Klick eine Methode des Objekt aufrufen können, werden bis zum Neustart der Applikation disabled
Get natürlich nicht. Woher soll .NET wissen, dass Du nicht doch mal irgendwann wieder die Buttons enablest <g>? Also einfach die Referenzen löschen und fertig

Zitat von Fingolfin:
Ich mache hauptsächlich Multimedia-Anwendungen mit einer gehörigen Menge beweglicher Grafik.
Nutze IDisposable.

Zitat von Fingolfin:
andere Objekte darüber benachrichtigt, damit diese irgendein Verhalten ausführen können.
Nutze IDisposable.

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.

......
Daniel W.
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
Fingolfin

Registriert seit: 7. Okt 2003
62 Beiträge
 
#15

Re: Interfaces in DotNet ganz anders?

  Alt 3. Dez 2004, 23:00
Danke erstmal für die vielen Kommentare.

Zitat von Robert_G:
Zitat von Fingolfin:
1) Kann ich dem GC trauen?
Solange du nicht wie ein VB'ler wild drauf los erzeugst ist alles in Butter.
und

Zitat von sakura:
Ja
Nunja, seid nicht sauer, aber ich hatte auf eine etwas technischer belegte Antwort gehofft. Aber ich nehme mal an, eure Überzeugung ist erfahrungsbedingt, also werdet Ihr damit sicher recht haben.

Zitat von Robert_G:
Zitat von Fingolfin:
2) PerformanceIch 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.
Und du bist dir sicher, dass du da mit D32 besser dran warst? In Delphi32 gibt es einen messbaren Performance hit bei der Verwendung von Interfaces. Außerdem
Nun, ein kleine Unterschied besteht schon zwischen ein paar Interfaces und 100 MB oder mehr Grafik im Speicher.

Zitat von Robert_G:
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.
Ich denke, das ist Ansichtssache. Wenn ich Interfaces benutze baue ich ja gerade auf eine recht starke Abstrahierung. Mit anderen Worten, die Notwendigkeit einen Self-Parameter zu benötigen, sollte meines Erachtens bei Interfaces gar nicht zu Tage treten.

Zitat von Robert_G:
Da du in .Net die Referenzzählung nicht mehr selbst machen muss, sieht es auch gleich viel "aufgeräumter" aus.
Das verwirrt mich jetzt etwas. In Delphi besteht doch im Grunde keine Notwendigkeit selbst an der Referenzzählung rumzuspielen?!? Das käme eigentlich nur bei der Mischung von Interface- und Objektreferenzen zum Tragen und das habe ich immer vermieden, weil es eben so stark fehleranfällig ist.

@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.
  Mit Zitat antworten Zitat
Robert_G
(Gast)

n/a Beiträge
 
#16

Re: Interfaces in DotNet ganz anders?

  Alt 4. Dez 2004, 00:28
Zitat von Fingolfin:
Zitat von Robert_G:
Da du in .Net die Referenzzählung nicht mehr selbst machen muss, sieht es auch gleich viel "aufgeräumter" aus.
Das verwirrt mich jetzt etwas. In Delphi besteht doch im Grunde keine Notwendigkeit selbst an der Referenzzählung rumzuspielen?!? Das käme eigentlich nur bei der Mischung von Interface- und Objektreferenzen zum Tragen und das habe ich immer vermieden, weil es eben so stark fehleranfällig ist.
Du hast dich selbst beantwortet.
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...
  • Die GC interessiert sich überhaupt nicht für unmanaged resources und ob diese eine Instanz einer managed Klasse referenzieren.
    Sie wird dir deshalb diese Instanz wegklauen, wenn sie von keiner anderen managed Instanz referenziert wird oder du ihr Leben nicht verlängerst.
    • Zum Beispiel mit GC.SupressFinalize/GC.ReRegisterForFinalize kannst du verhindern, dass die Instanz vorzeitig zerstört wird:
      Delphi-Quellcode:
      //verhindern, dass die Instanz zerstört wird
      GC.SupressFinalize(EineInstanz);
      //mache irgendwas...
      GC.ReRegisterForFinalize(EineInstanz);
      // ab jetzt kann die Instanz wieder von der GC zerstört werden
    • Sehr simpel ist KeepAlive, aber man kann es sicher nicht überall verwenden.
      Wenn du in einer Methode das da schreibst:GC.KeepAlive(EineInstanz); Dann weiß die GC, dass du mindestens bis zu diesem Punkt eine Referenz auf die Instanz bewahren willst.

      Delphi-Quellcode:
      SomeClass EineInstanz= new SomeClass();
      //irgend ein unmanaged call, der zum Bleistift EineInstanz als Parameter braucht...
      //und hier gleich noch einer...
      //ohne GC.KeepAlive könnte EineInstanz schon nach/während des ersten Calls tot sein
      GC.KeepAlive(EineInstanz);
      // ab jetzt kann die GC diese Instanz zerstören

  • Die GC läuft in allen Nicht-Service-Applications (hübsches Wort ) als Hintergrundthread.
    d.h.: Du hast gerade mit deinen 100MB an Sprites gespielt, nun machst du etwas anderes und erwartest, dass die GC aufräumt...
    Dumm ist nur, dass "etwas anderes" die CPU ziemlich beansprucht, "noch etwas anderes" die 2. CPU, ... außerdem hat dein System noch genügend RAM frei.
    Die GC sieht jetzt gar nicht ein warum sie der armen CPU den Stress des Aufräumens antun sollte. -> Sie wird also nicht aufräumen.
    Du weißt aber, dass du den Speicher gleich brauchen wirst. (Hellsehen ist eines der Dinge, die M$ noch nicht in die GC integriert hat -> kommt wohl in .Net 0815 )
    Deshalb kannst du die GC mit:GC.Collect(); ... dazu anweisen, zu sortieren.
    Wenn du erst dann weitermachen willst, wenn der Speicher frei ist:
    GC.WaitForPendingFinalizers(); Dadurch wird dein Thread pausiert bis alle Instanzen, die von der GC als NullReferenzen erkannt wurden, weg sind.
    Damit gehst du sicher, dass der Speicher frei ist, aber du hast kurzeitig den Performancegewinn durch einen automen "Aufräum-thread" aufgegeben.
    Diesen, etwas krassen Schritt, habe ich bisher immer wieder aus meinen Code entfernt, da es (nach ein paar Tests) einfach nicht notwendig war.
Zitat von Fingolfin:
Wenn jemand die vielleicht mal in einem Satz niederschreiben könnte, bezugnehmend auf meine Verwunderung, wäre ich überglücklich
War wohl doch mehr als ein Satz...
So jetzt kann es die Mieze zerreißen.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:27 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz