簡體   English   中英

當我們從`using'塊中的方法返回時,如何處理內存?

[英]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塊,其中foofinally部分中被處理掉。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM