次の方法で共有


リソース管理: use キーワード

このトピックでは、リソースの初期化と解放を制御できるキーワード useusing 関数について説明します。

リソース

リソースという用語は、複数の方法で使用されます。 はい。リソースは、文字列、グラフィックスなど、アプリケーションが使用するデータにすることができますが、このコンテキストでは、 リソース はソフトウェアまたはオペレーティング システムのリソース (グラフィックス デバイス コンテキスト、ファイル ハンドル、ネットワークとデータベース接続、待機ハンドルなどのコンカレンシー オブジェクトなど) を参照します。 アプリケーションでこれらのリソースを使用するには、オペレーティング システムまたは他のリソース プロバイダーからリソースを取得した後、リソースをプールにリリースして、別のアプリケーションに提供できるようにする必要があります。 問題は、アプリケーションがリソースを共通プールに解放しない場合に発生します。

リソースの管理

アプリケーション内のリソースを効率的かつ責任を持って管理するには、リソースを迅速かつ予測可能な方法で解放する必要があります。 .NET Framework は、 System.IDisposable インターフェイスを提供することでこれを行うのに役立ちます。 System.IDisposableを実装する型には、リソースを正しく解放するSystem.IDisposable.Dispose メソッドがあります。 適切に記述されたアプリケーションでは、限られたリソースを保持するオブジェクトが不要になったときに、 System.IDisposable.Dispose がすぐに呼び出されることを保証します。 幸いなことに、ほとんどの .NET 言語では、これを簡単にするためのサポートが提供されており、F# も例外ありません。 dispose パターンをサポートする便利な言語コンストラクトには、 use バインドと using 関数の 2 つがあります。

バインドを使用する

use キーワードには、let バインドに似た形式があります。

use value = expression

let バインディングと同じ機能を提供しますが、値がスコープ外になったときに値にDisposeする呼び出しが追加されます。 コンパイラは値に null チェックを挿入し、値が null場合、 Dispose の呼び出しは試行されないことに注意してください。

次の例は、 use キーワードを使用してファイルを自動的に閉じる方法を示しています。

open System.IO

let writetofile filename obj =
   use file1 = File.CreateText(filename)
   file1.WriteLine("{0}", obj.ToString() )
   // file1.Dispose() is called implicitly here.

writetofile "abc.txt" "Humpty Dumpty sat on a wall."

useの複数のインスタンスは、宣言されている逆の順序で破棄されます。 つまり、最初の use は最後にリリースされます。

コンピュテーション式では use を使用できます。この場合、 use 式のカスタマイズされたバージョンが使用されます。 詳細については、「 シーケンス非同期式タスク式コンピュテーション式」を参照してください。

using Function

using関数の形式は次のとおりです。

using (expression1) function-or-lambda

using式では、expression1 は破棄する必要があるオブジェクトを作成します。 expression1 (破棄する必要があるオブジェクト) の結果は、関数またはラムダに対する引数、になります。これは、expression1 によって生成された値と一致する型の残りの 1 つの引数を受け取る関数か、その型の引数を受け取るラムダ式のいずれかになります。 関数の実行の最後に、ランタイムは Dispose を呼び出し、リソースを解放します (値が nullされていない限り、Dispose の呼び出しは試行されません)。

次の例では、ラムダ式を使用した using 式を示します。

open System.IO

let writetofile2 filename obj =
    using (System.IO.File.CreateText(filename)) ( fun file1 ->
        file1.WriteLine("{0}", obj.ToString() )
    )

writetofile2 "abc2.txt" "The quick sly fox jumps over the lazy brown dog."

次の例は、関数を使用した using 式を示しています。

let printToFile (file1 : System.IO.StreamWriter) =
    file1.WriteLine("Test output");

using (System.IO.File.CreateText("test.txt")) printToFile

この関数は、いくつかの引数が既に適用されている関数である可能性があることに注意してください。 これを示すコード例を次に示します。 文字列 XYZを含むファイルが作成されます。

let printToFile2 obj (file1 : System.IO.StreamWriter) =
    file1.WriteLine(obj.ToString())

using (System.IO.File.CreateText("test.txt")) (printToFile2 "XYZ")

using関数とuseバインディングは、同じことを実現するほぼ同等の方法です。 using キーワードを使用すると、Disposeが呼び出されるタイミングをより詳細に制御できます。 usingを使用すると、関数またはラムダ式の末尾にDisposeが呼び出されます。use キーワードを使用すると、Disposeは、含まれるコード ブロックの末尾に呼び出されます。 一般に、using関数の代わりにuseを使用する必要があります。

こちらも参照ください