使用語句基礎

using 是一個語法糖,可以保證資源被清理而不需要明確的 try-finally 塊。這意味著你的程式碼將更加清晰,並且你不會洩漏非託管資源。

標準的 Dispose 清理模式,用於實現 IDisposable 介面的物件(FileStream 的基類 Stream 在 .NET 中執行):

int Foo()
{
    var fileName = "file.txt";

    {
        FileStream disposable = null;

        try
        {
            disposable = File.Open(fileName, FileMode.Open);

            return disposable.ReadByte();
        }
        finally
        {
            // finally blocks are always run
            if (disposable != null) disposable.Dispose();
        }
    }
}

using 通過隱藏顯式 try-finally 簡化了語法:

int Foo()
{
    var fileName = "file.txt";

    using (var disposable = File.Open(fileName, FileMode.Open))
    {
        return disposable.ReadByte();
    }
    // disposable.Dispose is called even if we return earlier
}

就像 finally 塊總是執行而不管錯誤或返回,using 總是呼叫 Dispose(),即使出現錯誤:

int Foo()
{
    var fileName = "file.txt";

    using (var disposable = File.Open(fileName, FileMode.Open))
    {
        throw new InvalidOperationException();
    }
    // disposable.Dispose is called even if we throw an exception earlier
}

注意: 由於無論程式碼流如何都保證呼叫 Dispose,因此確保 Dispose 在實現 IDisposable 時不會丟擲異常是個好主意。否則,新異常將覆蓋實際異常,從而導致除錯噩夢。

從使用塊返回

using ( var disposable = new DisposableItem() )
{
    return disposable.SomeProperty;
}

由於 using 塊翻譯的 try..finally 的語義,return 語句按預期工作 - 在執行 finally 塊之前評估返回值並處理該值。評估順序如下:

  1. 評估 try 的身體
  2. 評估並快取返回的值
  3. 執行 finally 塊
  4. 返回快取的返回值

但是,你可能不會返回變數 disposable 本身,因為它將包含無效的,已丟棄的引用 - 請參閱相關示例