2017-08-24 7 views
-1

Angenommen, Sie haben dies:Was passiert mit Objekten, die innerhalb einer Funktion deklariert sind und die als Rückgabewert verwendet werden? Warum werden sie bei der Rückkehr nicht entzogen?

static Object foo() 
{ 
    Object test = new Object(); 
    return test; 
} 

Object output = foo(); 

in C# Mindestens (Standardcode links aus), wird das Programm nicht abstürzen, wenn Sie versuchen, Ausgabe zu verwenden, obwohl es in foo erklärt auf das gleiche Objekt ist zeigt. Warum wurde es nicht sofort freigegeben? Und wenn dies eine schlechte Methode ist, um Objektrückgabewerte zu behandeln, gibt es einen besseren Weg, damit umzugehen?

+1

"Warum wurde es nicht sofort freigegeben?" Weil Garbage Collection, und wir übergeben Referenzen. Liebe in C# muss niemals sagen, dass du fertig bist. –

+0

"Liebe in C# muss niemals sagen, dass du fertig bist." - Das ist tief @ JeroenMostert: D Ken: Durch die Zuweisung des Verweises auf "Ausgabe" gibt es einen starken Verweis auf das Objekt innerhalb der Funktion erstellt. Deshalb wird der GC das nicht sammeln. Warum sollte das "eine schlechte Methode sein, Objektrückgabewerte zu verarbeiten"? Wie sonst würden Sie einen Referenztyp zurückgeben? – Fildor

+2

Dreh es um, warum * sollte * das Programm abstürzen? Ist es nicht klar, was du hier machen willst? Möchten Sie, dass das Programm abstürzt, weil Sie es nicht ausdrücklich aufgefordert haben, eine Kopie für den Zugriff außerhalb der Funktion zu erstellen? Möchtest du genau wissen, was auf dem Stapel ist und was auf dem Haufen an jedem Punkt ist?Wenn Sie "Ja" sagten, können Sie eine wundervolle Karriere als C-Programmierer haben - aber Sie müssen (meistens) nicht dieses mentale Gepäck herumtragen, wenn Sie C# programmieren. –

Antwort

0

Referenz übergeben. Objekt ist ein Referenztyp, dh jede einzelne Änderung (einschließlich der Zuweisung) wird in dem Block beibehalten, in dem dieses Objekt deklariert wurde.

Wenn Sie einige C/C++, Verweise sind etwas automanaged Zeiger.

Zurück es ist keine schlechte Praxis, aber man sollte vorsichtig sein. Wenn Sie die Referenz zurückgeben und später zuweisen, verlieren Sie die vorherige Version, wenn Sie sie bereits vorher zugewiesen haben. Nochmals, wenn Sie etwas C getan haben, ist es so, als ob Sie Ihren Zeiger auf einen zweiten zugewiesenen Speicherbereich richten und den ersten (im vorherigen Beispielfall) lassen.

2

Die GC wird nur Objekte sammeln, die keine erreichbaren Referenzen haben (wenn es so ist). In Ihrem Beispiel:

static object foo() 
{ 
    object test = new object(); 
    return test; 
} 

object output = foo(); 

Die Instanz von test verwiesen wird, auch durch output referenziert, wenn foo zurückkehrt. Auch wenn test ist nicht mehr ein erreichbar Referenz, output immer noch ist daher die Instanz seine "zeigt" ist kein Kandidat für die Sammlung.

Das folgende Beispiel ist radikal anders:

static object foo() 
{ 
    object test = new object(); 
    return test; 
} 

foo(); 

Hier wird die Instanz von test verwiesen ist ein gültiger Kandidat für die Sammlung einmal foo zurückkehrt (oder sogar vor, sondern lässt diese Optimierungen ignorieren), denn sobald foo returns, es gibt keine erreichbaren Verweise auf das Objekt.

Beachten Sie, dass ich erreichbar Referenzen verwende. Ein Objekt kann über gültige Verweise verfügen, die auf es verweisen, aber dennoch ein Kandidat für die Sammlung sein, wenn das Objekt, das den Verweis enthält, ebenfalls ein Kandidat für die Sammlung ist. Die GC ist intelligent genug über diese Art von Zyklen:

class A { public B b; } 
class B { public A a; } 

void Foo() 
{ 
    A a = new A(); 
    B b = new B(); 
    a.B = b; 
    b.A = a; 
} 

Foo(); //both a and b are elegible for collection once Foo exists. 
Verwandte Themen