73

「使用中」ブロックを使用すべき (または使用すべきでない) 特定の例はありますか?

using(SomeType t = new SomeType()){
    ...
}
4

14 に答える 14

101

一部のオブジェクトは、処理が完了したときに何らかのアクションを実行する必要があります。通常、これは、オブジェクトが、破棄する必要のあるある種のリソースを使用しているためです。たとえば、File クラスのファイル オブジェクトがあり、このオブジェクトがファイル システムからファイルを開く場合、ファイル システム内のファイルを再度閉じる必要があります。

ファイル オブジェクトをそのままにして、file.Close() を呼び出すのを忘れた場合、ガベージ コレクター (GC) が実行され、ファイル オブジェクトがまだ使用されていないことが判明するまで、クリーンアップされません。ガベージ コレクターをいつ実行するかは、共通言語ランタイム (CLR) に任せて決定する必要があります。ファイルの処理が完了した後、GC がしばらく実行されない場合、ファイルが長時間開いたままになる可能性があります。多くのファイル オブジェクトがある場合、または何かがファイルを開こうとしているが、あなたが残したファイル オブジェクトがまだぶらぶらしているためにできない場合、これは大きな問題を引き起こす可能性があります。

この問題を解決するために、C# には IDisposable インターフェイスがあります。これには Dispose というメソッドが 1 つあります。クリーンアップが必要なクラスは、この Dispose メソッドを実装します。これにより、リソースを使用するオブジェクトをクリーンアップするための標準的な方法が得られます。Dispose を呼び出す必要があるクラスはたくさんあります。これに関する問題は、コードが Dispose の呼び出しで覆われていることです。オブジェクトを新しくした場所と Dispose を呼び出してクリーンアップする場所が異なるため、追跡するのが難しいです。そのため、コードをよく調べて、適切な場所に Dispose の呼び出しがあったことを注意深く確認する必要がありました。

この問題を解決するために、C# では「using」キーワードが導入されました。オブジェクトを新しく作成する場所の周りに「using」キーワードを置くことができます。これにより、Dispose が呼び出されることが保証されます。Dispose が呼び出されることを保証します...たとえ using ステートメントの本体内でスローされた例外があっても。

そのため、リソースを割り当てるオブジェクトを確実にクリーンアップしたい場合は、'using' を使用する必要があります。


using は、スタック上、つまり関数内で宣言されているオブジェクトに対してのみ使用できます。クラスのメンバーとして宣言されているオブジェクトでは機能しません。それらについては、自分で Dispose を呼び出す必要があります。Dispose を必要とする任意のメンバー オブジェクトで Dispose を呼び出すことができるように、クラスに Dispose を実装する必要がある場合があります。


これらに対して呼び出す必要がある一般的なオブジェクトは、ファイル、データベース接続、ペンやブラシなどのグラフィックス オブジェクトです。


2 つの操作を同時に実行したい場合にも使用されることがあります。たとえば、コード ブロックが入力されたときと終了したときにログ ステートメントを書きたい場合は、次のように使用できるログ クラスを書くことができます。

using( Log log = new Log("Doing stuff") )
{
    // Stuff
}

ログ クラスのコンストラクターでメッセージを書き出すことができ、Dispose メソッドでもメッセージを書き出すことができます。ファイナライザー (~Log) を実装して、Dispose メソッドが呼び出されない場合にアサートして、'using' が 'new Log' の周囲に確実に記憶されるようにします。

于 2009-02-19T21:47:33.820 に答える
95

SomeTypeクラスがIDisposable.

于 2009-02-19T21:04:45.237 に答える
13

using型が を実装する場合はいつでも使用してください。とにかく/IDisposableブロックでラップする場合を除き、(好みの外観に応じて)ブロックを使用することもできます。trycatchfinally

于 2009-02-19T21:05:12.570 に答える
11

声明を出す必要がある場合は、他の多くの回答が示されています。具体的にステートメントを持ってはいけないusing場合に対処したい:using

using現在の関数のスコープ外でオブジェクトを使用する必要がある場合は、ブロックを作成しないでください。良い例は、データベース接続を返すファクトリ メソッドや、データリーダーを返す必要があるメソッドです。どちらの場合でも、usingステートメントを使用してオブジェクトを作成すると、メソッドが返される前に破棄されるため、メソッドの外では使用できません。

これらのオブジェクトが破棄されていることを確認したいので、usingどこかにステートメントが必要になる場合があります。オブジェクトが実際に作成されるメソッドには含めないでください。using代わりに、関数呼び出し自体をステートメントでラップできます。

于 2009-02-19T21:48:36.970 に答える
4

SomeType が IDisposable を実装する場合。

これは、クリーンアップが必要な管理されていないリソースを SomeType が使用しているという開発者の手がかりです。

于 2009-02-19T21:05:21.367 に答える
4

例:

        using(SqlConnection MyConnection = new SqlConnection("Connection string"))
        {
            MyConnection.Open();

            //...

            // 1. SQLConnection is a type that implements IDisposable
            // 2. So you can use MyConnection in a using statement
            // 3. When using block finishes, it calls Dispose method of 
            // SqlConnection class
            // 4. In this case, it will probably close the connection to 
            // the database and dispose MyConnection object

        }

IDisposable を実装する独自のオブジェクトを作成できます。

public class MyOwnObjectThatImplementsIDisposable : IDisposable
{

    //... some code

    public void Dispose()
    {
        // Put here the code you want to be executed when the
        // using statement finish.
    }
}

したがって、using ステートメントで MyOwnObjectThanImplementsIDisposable タイプのオブジェクトを使用できます。

        using(MyOwnObjectThatImplementsIDisposable MyObject = new MyOwnObjectThatImplementsIDisposable)
        {

            // When the statement finishes, it calls the 
            // code you´ve writed in Dispose method
            // of MyOwnObjectThatImplementsIDisposable class
        }

お役に立てれば

于 2009-02-19T21:21:59.040 に答える
2

サマリールールが必要な場合。IDisposableを使用しているオブジェクトで、キャッチがない場合はいつでも、usingを使用してください。基本的に、このパターンを使用しています。

try
{
  //instantiate and use object
}
finally
{
  //dispose object
}

キャッチが必要ない場合は、を使用すると入力を節約できます。これは良いことです。

于 2009-02-20T03:56:59.547 に答える
2

このコンテキストでは、usingステートメントは IDisposable を実装する型に便利です。コード ブロックがusingステートメントのスコープを終了すると、Dispose()暗黙的に呼び出されます。使用後すぐに処分したいものを扱うときの良い習慣です。

于 2009-02-19T21:05:46.983 に答える
2

usingブロックの使用に注意する必要がある特定のインスタンスの 1 つは、WCF サービス クライアントを使用する場合です。

この MSDN の記事に記載されているように、WCF クライアント (実装しているIDisposable) をusingブロックでラップすると、クライアントが障害状態のままになるエラー (タイムアウトや通信の問題など) を隠すことができます。簡単にDispose()言うと、 が呼び出されると、クライアントのClose()メソッドが起動しますが、エラーが発生した状態であるため、エラーがスローされます。元の例外は、2 番目の例外によってマスクされます。良くない。

MSDN の記事自体にあるものを含め、さまざまな回避策があります。その他はIServiceOrientedblog.davidbarret.netにあります。

私は最後の方法を好みます。

于 2009-02-19T23:16:04.527 に答える
1

「使用する」lo C# 言語を追加する根本的な理由は次のとおりです。GC が IDisposable を呼び出すのを待つのが意味をなさないほど十分にリソースが不足している可能性があります。たとえば、DB 接続です。try/catch/finally を使用すると、ダングリング接続になることはありませんが、GC が起動しなくなるまで接続がハングしたままになり、これにはしばらく時間がかかることがあります (明示的に閉じない場合)。「using」を使用する場合(しゃれを許してください)、接続を閉じるのを忘れた場合や、usingブロック内で例外が発生した場合でも、すぐに接続を解放します。
もう 1 つの理由は、以前の投稿で述べたように、プログラマーが常に最終的にクリーンアップを使用するとは限らないことです。例外が発生した場合に finally を使用しないと、リソースのリークが発生します…</p>

于 2009-02-19T22:48:14.220 に答える
1

主なルールは次のとおりです。 * オブジェクトが IDisposable インターフェイスを実装する場合は、USING ステートメントを使用します。

このインターフェイスは、オブジェクトのリソースを解放する Dispose メソッドを提供します。このメソッドが呼び出されない場合、CLR がガベージ コレクションを実行するため、オブジェクトはメモリ内にとどまります。プログラマーが USING ステートメントを使用すると、最後にオブジェクトが破棄され、すべてのリソースが解放されます。

使用されなくなったすべてのリソースをできるだけ早く解放することが非常に重要です。

詳細については、次のリンクにアクセスしてください: microsoft

于 2009-02-19T21:14:53.940 に答える
0

1 つの状況は、コード ブロックの先頭で何かを実行し、ブロックの最後で無条件に (例外が発生した場合でも) 元に戻したい場合です。

作成する (および using 内で呼び出す) 使い捨てクラスの ctor がアクションを実行し、Dispose メソッドがそのアクションを元に戻します。これは通常、私がそれを使用する方法です。

于 2009-02-19T21:06:27.433 に答える
0

他の人はすでに「IDisposable」について言及しています。

ただし、「using」ステートメントを使用する際の注意事項の 1 つは、「someType」が破棄されても、「using」内でスローされた例外はキャッチされないことです。

したがって、次のスニペットでは、

using (SomeType t = new SomeType()){
    throw new Exception("thrown within using");
}

throw new Exception("thrown within using");無視してはいけません。

于 2009-02-19T21:15:55.513 に答える
0

また、何かが実装されている場合、およびデータベース接続やファイルハンドルなどの管理対象外のリソースを処分したい場合 は、using()ステートメントを使用することも追加します。IDispose

List<T>T が名前とアドレスを保持するオブジェクトのようなものであるa などの通常のオブジェクトである場合Customer、その必要はありません。ガベージ コレクターは、これを管理するのに十分スマートです。ただし、ガベージ コレクタは接続を接続プールに戻したり、ファイル ハンドルを閉じたりしません。

于 2009-02-19T23:00:43.490 に答える