[英]How is memory handled when we return from a method in a `using` block?
請考慮以下代碼:
public Bar GetBar()
{
using(var foo = new Foo())
{
return foo.Bar;
}
}
這是漏洞,還是foo.Dispose()
調用? 由於foo
被處置,返回值是否可能無效?
這里的答案很接近但不完整,並且不一致。
這是漏洞,還是foo.Dispose()調用?
Dispose
被稱為。 using
塊被轉換為try
/ finally
塊,其中foo
在finally
部分中被處理掉。 finally
將在try
完成后調用(無論是異常還是自然)並在返回調用者之前調用。 因此幾乎在所有情況下都會調用Dispose
(除非出現非常嚴重的異常,例如內存不足,線程中止等)
由於foo被處置,返回值是否可能無效?
當然,如果Dispose
做了一些事情來使Bar
引用的對象無效,那么是的,肯定會返回一個“無效”的引用。 但這必須在Foo
明確 。 處置對象不會自動處理所有屬性。
這是否泄漏?
對於幾乎任何實現IDisposable的對象來說,這是一個很好的編碼實踐,因為它確保一旦“使用”的變量超出范圍(例如,代碼離開使用塊),就會調用dispose方法。 有一些例外(WCF客戶端,自定義代碼不遵循良好的IDisposable實踐),但最好將任何IDisposable包裝在using塊中,除非您有特殊原因不這樣做。
由於foo被處置,返回值是否可能無效
這取決於Foo中Dispose
方法的作用。 例如,如果您嘗試調用引用已關閉/處置的SQLConnection的SQLCommand,您將獲得異常。 讓我們看一個使這種行為顯而易見的例子。
public class Foo : IDisposable
{
public Foo()
{
ComplexType = new ComplexType();
}
public ComplexType ComplexType { get; set; }
public void Dispose()
{
ComplexType = null;
GC.Collect();
}
}
現在這段代碼可以訪問我們的Foo:
static void Main(string[] args)
{
Foo foo;
ComplexType complexType;
using (var newFoo = new Foo())
{
foo = newFoo;
complexType = newFoo.ComplexType;
}
Console.WriteLine(complexType.SomeProperty); // This works :)
Console.WriteLine(foo.ComplexType.SomeProperty); // Throws an exception because ComplexType is NULL
Console.ReadKey();
}
奇怪吧? 發生這種情況的原因是因為在Foo構造函數中我們創建了一個新的ComplexType並將其存儲在一個內存地址中。 Foo.ComplexType屬性包含對內存地址的引用 。 當我們調用dispose時,我們將引用設置為null,但實際對象不是垃圾收集的,因為我們在調用代碼中有對它的其他引用,所以我們不能再通過foo.ComplexType
屬性訪問它,但它是仍然可以通過complexType
變量訪問。 還要注意,即使已將foo
分配給已處置的對象, foo
也不為null。 因為我們的Foo
實例仍然存在引用,盡管它位於using塊之外,但它仍處於活動狀態,因為在該引用存在時無法收集它。
現在,如果Dispose
方法更改了SomeProperty,則可能(取決於它的更改方式),更改COULD傳播出來並使結果無效。
我想這個故事的寓意是,如果你開始玩弄已被處置的物體,你可以體驗(或創造)各種奇怪的行為,但這取決於處置過程中被處置物體的作用。 我不建議將其作為一種做法,因為大多數物品不應在處理后使用。 在使用塊內作為原子單元執行“工作”,然后讓對象死亡。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.