2016-03-09 3 views
5

Woher weiß ich, ob eine Klasse in C# nicht verwaltet wird? Wenn ich sie in einer selbstdefinierten Klasse verwende, weiß ich, ob ich die IDisposable-Schnittstelle implementieren muss ?Woher weiß ich, ob eine Klasse ein Wrapper für eine nicht verwaltete Ressource ist?

Wenn ich diese article im MSDN-Netzwerk richtig bekomme, muss ich immer die IDisposible-Schnittstelle implementieren, wenn ich eine nicht verwaltete Ressource verwenden.

Ich habe ein kleines Beispiel so erstellt, dass Sie hier finden können:

dass Datei ist eine unamanged ressource
class TestClass 
{ 
    private StreamReader reader; 

    public UsingTestClass() 
    { 
     reader = File.OpenText("C:\\temp\\test.txt"); 

     string s; 
     while (!string.IsNullOrEmpty(s = reader.ReadLine())) 
     { 
      Console.WriteLine(s); 
     } 

    } 
} 

Die folgenden MSDN article sagt zum Beispiel, das auch in meiner Test-Klasse verwendet wird. Wie kann ich also sehen, dass diese Klasse nicht integriert ist? Der Compiler und ReSharper haben sich nicht beschweren.

Vielen Dank im Voraus.

+1

Einfach: Sie können nicht. – ckruczek

+0

Also, was ist die beste Praxis, um in Fällen zu handeln? Besonders von Ihnen verwenden Bibliotheken von Drittanbietern? – Fabian

+5

Alles, was IDisposable implementiert, sollte entfernt werden, wenn Sie damit fertig sind. – erikH

Antwort

6

Wie kann ich wissen, ob eine Klasse in C# unmanaged ist

das dich auf dem falschen Weg bekommt sofort, alle Klassen in C# verwaltet werden. Die Sprache unterstützt überhaupt keine nicht verwalteten Klassen. Keine der .NET-Sprachen, außer einem: C++/CLI. Dies ist eine eher untypische Sprache, die speziell dafür entwickelt wurde, einem Programmierer die Verwendung einer nativen C++ - Klasse zu erleichtern. Die Verwendung dieser Sprache ist spezialisiert und für diese Frage nicht relevant.

Es kommt darauf an, ob die verwaltete Klasse ein Wrapper für eine nicht verwaltete Ressource ist. Ein Wrapper ist die Art von Klasse, die über eine rein verwaltete Schnittstelle verfügt, aber intern eine nicht verwaltete Ressource verwendet, normalerweise über pinvoke mit dem Attribut [DllImport]. Die Ressource wird fast immer mit einem IntPtr dargestellt. Ein nicht verwalteter Griff oder Zeiger.

Ein solcher Wrapper benötigt einen Finalizer, um sicherzustellen, dass die nicht verwaltete Ressource immer freigegeben wird. Wenn das nicht passiert, dann haben Sie eine Leck, die Art von Fehler, der (schließlich) ein Programm abstürzt, wenn das Betriebssystem über ein Programm verärgert wird, das zu viele Ressourcen verwendet.

Und da es einen Finalizer hat, implementiert es auch IDisposable. Ermöglichen, dass ein Programm die nicht verwaltete Ressource vorzeitig freigibt, bevor der GC den Finalizer aufruft. Die Verwendung der Dispose() - Methode oder unter Verwendung der-Anweisung ist optional. Der Finalizer ist gut genug, um sicherzustellen, dass der Job ausgeführt wird.

Aber manchmal ist der Finalizer nicht gut genug, weil ein Programm nicht schnell genug Müll erzeugt und dann ist es ziemlich wichtig, dass Sie helfen. Sie können nicht wirklich wissen, ob Sie helfen müssen, also tun die meisten .NET-Programmierer immer. Und eine Untergruppe hat nie ein Problem in Jahren der Programmierung bemerkt und nie bemerkt. Wir hören schließlich von ihnen SO an :)


Ihr Beispiel eines Stream ist gut, um zum nächsten Schritt zu gelangen. StreamReader umschließt eine nicht verwaltete Ressource nicht. Der gesamte Code ist in C# geschrieben und es hat keinen Pin-Voke, es gibt keinen unmanaged Bone in seinem Körper. Und deshalb nicht haben einen Finalizer. Hat aber immer noch eine Dispose() -Methode.

StreamReader wurde "infiziert".Es ist auch eine Wrapper-Klasse, aber für einen Stream, kein IntPtr. Ein rein verwalteter abstrakter .NET-Typ, der selbst ein Wrapper ist. Welche implementiert IDisposable, jetzt StreamReader hat, um es auch zu implementieren. Wenn Sie also die Dispose() - Methode des StreamReaders aufrufen, kann die Stream.Dispose() -Methode ausgeführt werden.

Dies ist Layering bei der Arbeit gibt es eine Hierarchie von Klassen. StreamReader umschließt den Stream, der FileStream umhüllt, der SafeFileHandle umhüllt, wobei eigentlich den IntPtr umschließt. Nur SafeFileHandle hat einen Finalizer.

Das Verstehen der Schichten ist der Ort, an dem jeder aufgibt, der ziemlich genaue Einblicke in die Struktur dieser .NET-Klassen erfordert. Sie können dorthin gelangen, aber es dauert Jahre. Es gibt drei grundlegende Verknüpfungen:

  • Haben Sie ein Verständnis, wie ein Betriebssystem funktioniert. Gibt Ihnen den Einblick, dass eine Datei eine Betriebssystemressource ist, wetten Sie darauf, dass wenn Sie eine Datei verwenden, sie entsorgt oder geschlossen werden muss.

  • Verwenden Sie den MSDN Library-Artikel für die Klasse, die Sie verwenden. Wenn Sie sehen, dass es eine Dispose() -Methode hat, gibt es fast immer einen guten Grund, sie zu verwenden. Manchmal gibt es nicht, aber Sie werden nie falsch liegen, wenn Sie es trotzdem benutzen.

  • In Schwierigkeiten geraten, machen Sie alle Fehler, die jeder Programmierer machen muss, verwenden Sie SO oder einen Speicherprofiler, um herauszufinden, was Sie falsch gemacht haben. Nichts ist falsch daran zu lernen, wie man es richtig macht.

+0

Zusammenfassung: Also, wenn wir 'using' oder' Dispose() 'in jeder Klasse verwenden, die' IDisposable' implementiert, sind wir immer sicher? Gibt es Fälle, in denen wir nicht 'Dispose()' auf 'IDisposable' nennen wollen? –

+0

Ich hasse Zusammenfassungen, versuche alle Wörter zu verstehen. Wenn ich weniger hätte benutzen können, hätte ich es getan. Nicht "immer sicher", entsorgen Sie kein Objekt, das anderweitig verwendet wird. –

+0

Vielen Dank für diese detaillierte Antwort. – Fabian

Verwandte Themen