C++ VS Java ft. C#: To RAII or not to RAII



  • Java, C++ und C sind immer noch die Spitzenreiter. Wer alle drei beherrscht, und dann noch Javascript und C#, ist gefragt.



  • Erhard Henkes schrieb:

    Java, C++ und C sind immer noch die Spitzenreiter. Wer alle drei beherrscht, und dann noch Javascript und C#, ist gefragt.

    Man kann nicht alle drei Beherrschen. Das ist wie Theologe, Physiker und BWLer sein, nur nicht ganz so schlimm.



  • @Mechanics
    Ich schreibe auch in C# oft Scope-Guard Objekte Klassen. Halt mit IDisposable + using statt Destruktor. In Java ist im Prinzip das selbe möglich mit IAutoClosable + try-with-resources.
    Ist aber zugegebenermassen sehr mühsam und natürlich viel fehleranfälliger als mit C++ (da man immer manuell das using/try-with-resources schreiben muss).

    Und für Fälle wo man ein IDisposable/IAutoClosable als Member hat gibt es sowieso keinen Sprach-Support.



  • Mir hat das using und IDisposable nie gefallen. War allerdings bevor ich intensiv mit C++ gearbeitet habe, damals war mir das Scope Guard Idiom noch nicht wirklich geläufig.
    Und das ist eigentlich mehr so ein Workaround. Funktioniert auch nicht wirklich, wenn man die Scope Guards z.B. in eine Liste reinstecken will oder irgendwie rumreichen... Und wenn man das als Member haben will, muss die umgebende Klasse auch IDisposable implementieren und dann muss man sich auch noch drum kümmern, dass die in einem using Block benutzt wird. Ich glaub fast, der Aufwand lohnt sich in C# nicht.



  • Lol, was heisst "der Aufwand lohnt sich nicht"?
    Was gibt's denn für ne Alternative?

    Mechanics schrieb:

    Funktioniert auch nicht wirklich, wenn man die Scope Guards z.B. in eine Liste reinstecken will oder irgendwie rumreichen...

    Du steckst ScopeGuards in C++ in Listen und reichst sie rum? Ich glaube du hast nicht verstanden was ScopeGuard bedeutet.



  • hustbaer schrieb:

    Du steckst ScopeGuards in C++ in Listen

    Zumindest in Listen stecke ich sie schon. z.B. eine Liste von Lock Files (oder einfach Files), Handles, Events, irgendwas... Wenn sich eine Funktion halt mehrere "Handles" holt und die am Ende einfach alle freigeben muss.
    Ob ich die jemals rumgereicht habe, weiß ich grad nicht... Könnte ich mir aber auch vorstellen. z.B. initialisiert eine Funktion irgendwas und "lockt" alles, was man dann brauchen wird, und gibt das Guard Objekt dann an eine andere Funktion weiter, oder speichert das als Member in einem Objekt, das später stirbt, oder was auch immer. Ich kann mir alle möglichen Einsatzszenarien vorstellen. Notfalls steckt man den "Scope Guard" (vielleicht eine etwas erweiterte Definition davon) halt in einen shared_ptr, da ist man in C++ flexibel.



  • Naja gut, solche Fällen kann man in C# auch mit ein paar mehr oder weniger einfachen Hilfsklassen abdecken.

    Ich hab' z.B. eine Klasse DisposeGuard .
    Die hat ne statische DisposeGuard.Alloc<T>(T target) Methode mit der ein DisposeGuard<T> erzeugt wird. Wenn dabei eine Exception fliegt wird versucht target.Dispose() aufzurufen.
    Weiters hat der DisposeGuard<T> eine Property Target - diese lässt sich auch nachträglich ändern.
    Und eine ReleaseTarget Methode, die das Target auf null setzt und den alten Wert zurückgibt.

    Und wenn DisposeGuard<T> disposed wird, dann halt sein Target -- es sei denn es ist null .

    Damit kann man schon mal ein paar schöne Sachen machen wie

    using (var fileGuard = DisposeGuard.Alloc(File.Open...))
    {
        TuFileVorbereiten(fileGuard.Target);
        return fileGuard.ReleaseTarget();
    }
    

    Weiters kann man sich - wenn man es brauchen sollte - eine DisposeGroup basteln. Die halt dann eine Reihe von Targets hat. Usw.

    Keine Hexerei.



  • Hallo hustbaer,

    Ich finde deine Vorgehensweise bei der C#-Geschichte ziemlich interessant.
    Kannst du vieleicht etwas Code posten, wie das Ganze so aussieht.



  • @case
    Passt hier nicht so ganz rein, daher hab ich im C# Forum nen eigenen Thread gemacht: https://www.c-plusplus.net/forum/p2463692#2463692



  • hustbaer schrieb:

    Passt hier nicht so ganz rein

    😃



  • Ja, ich weiss, ist vielleicht ein bisschen spät.
    Aber besser spät als nie.



  • @hustbaer, no problemo, stört mich nicht wirklich 😉

    P.S.: Findet ihr meinen alternativen Titel passend?



  • Nathan schrieb:

    Man muss sich in C++ auch keine Gedanken um Speicherverwaltung machen, das ist ein Mythos! Destruktoren ermöglichen keinerlei Leaks jeglicher Art und sind wesentlicher besser als GC, der sich nur um Speicher kümmert.

    Das stimmt auch nicht. Man kann auch mit Smartpointern Kreise bauen, die sich nicht mehr aufräumen. Man muss sich immer Gedanken um die Ownership machen, vorallem wenn mehrere an einem Projekt arbeiten.



  • Naja, aber dafür muss man es schon wollen.


Anmelden zum Antworten