15

using ステートメントは、using ブロックが終了したときに、「使用中」のオブジェクトの dispose メソッドを自動的に呼び出します。

しかし、これが必要/有益なのはいつですか?

たとえば、次のメソッドがあるとします。

public void DoSomething()
{
    using (Font font1 = new Font("Arial", 10.0f))
    {
        // Draw some text here
    }
}

オブジェクトはメソッドで作成されるため、ここに using ステートメントが必要ですか? メソッドが終了すると、Font オブジェクトは破棄されませんか?

または、メソッドが終了した後、別のときに Dispose メソッドが実行されますか?

たとえば、メソッドが次のような場合:

public void DoSomething()
{
    Font font1 = new Font("Arial", 10.0f);

    // Draw some text here
}

// Is everything disposed or cleared after the method has finished running?
4

14 に答える 14

20

'using' ステートメントは、データベース接続などの管理されていないオブジェクトを操作する場合に最も役立ちます。

このようにして、コード ブロックで何が起こっても、接続は閉じられ、破棄されます。

詳細については、CodeProject に関する次の記事を参照してください: http://www.codeproject.com/KB/cs/tinguusingstatement.aspx

于 2009-04-15T16:37:15.607 に答える
13

なしusingで (または手動で を呼び出しDispose()て)、オブジェクトは最終的に破棄されますが、確定的な時間ではありません。つまり、すぐに発生するか、2 日以内に発生するか、または (場合によっては) まったく発生しない可能性があります。

たとえば、ネットワーク接続などの場合、「いつでも」ではなく、完了したときに接続を閉じる必要があります。そうしないと、ソケットを占有してアイドル状態になります。

さらに、mutex ロックのようなものについては、「いつでも」それらを解放したくありません。そうしないと、デッドロックが発生する可能性があります。

于 2009-04-15T16:39:59.953 に答える
12

これ:

public void DoSomething()
{
    using (Font font1 = new Font("Arial", 10.0f))
    {
        // Draw some text here
    }
}

これに直接マップします:

public void DoSomething()
{
    {
        Font font1;
        try
        {
            font1 = new Font("Arial", 10.0f);
            // Draw some text here
        }
        finally
        {
            IDisposable disp = font1 as IDisposable;
            if (disp != null) disp.Dispose();
        }
    }
}

finally ブロックに注意してください。例外が発生した場合でも、オブジェクトは破棄されます。また、追加の匿名スコープ ブロックにも注意してください。これは、オブジェクトが破棄されるだけでなく、スコープ外になることも意味します。

ここでもう 1 つ重要なことは、廃棄がすぐに行われることが保証されていることです。それは決定論的です。using ステートメントまたは同様の構成要素がないと、オブジェクトはメソッドの最後でスコープ外になり、最終的に収集される可能性があります。その後、リソースは理想的には破棄され、システムが再利用できるようになります。しかし、「最終的に」しばらくは起こらないかもしれません。

したがって、「最終的に」が常に十分であるとは限りません。データベース接続、ソケット、セマフォ/ミューテックス、および (この場合) GDI リソースなどのリソースは、多くの場合、厳しく制限されており、すぐにクリーンアップする必要があります。using ステートメントは、これが確実に行われるようにします。

于 2009-04-15T17:02:21.257 に答える
9

using コンストラクトは、決定論的な破棄、つまりリソー​​スの解放を強制します。上記の例では、はい、「using」ステートメントを使用しない場合、オブジェクトは破棄されますが、推奨される使い捨てパターン (つまり、該当する場合はクラス ファイナライザーからのリソースの破棄) が実装されている場合のみです。問題のクラス(あなたの例では Font クラス)。IDisposableusing コンストラクトは、インターフェイスを実装するオブジェクトでのみ使用できることに注意してください。メソッドを「呼び出す」ために使用できるのは、オブジェクトにそのインターフェイスが存在することDisposeです。

さらに、ガベージ コレクターが範囲外の Font オブジェクトを収集することを決定した場合にのみ、基になるリソースが解放されます。.Net プログラミング (およびガベージ コレクターを備えたほとんどの言語) の重要な概念は、オブジェクトがスコープ外になったからといって、オブジェクトがファイナライズ/リリース/破棄などされるわけではないということです。オブジェクトが範囲外になった直後ではありません。

最後に、using ステートメントは try/finally コンストラクトを「焼き込み」、例外をスローする含まれているコードに関係なく Dispose が呼び出されるようにします。

于 2009-04-15T16:41:57.000 に答える
2

「使用」は、リソースを破棄する必要があり、IDisposable インターフェイスを実装するときに機能します。

于 2009-04-15T16:37:35.013 に答える
2

これが using が実際に行うことです(あなたの例に基づいて)

Font font1 = new Font(...);
try
{
    // code that uses font...
}
finally
{
    if (font1 != null)
        font1.Dispose();
}

したがって、変数が破棄されないようにする例外について心配する必要はありません。

于 2009-04-15T16:39:52.247 に答える
2

私にはとてもシンプルに思えます。

クラスが IDisposable を実装している場合、作成したすべてのインスタンスで Dispose を呼び出してくださいと要求しているようなものです。これは、そのようなインスタンスが作成されるたびに使用することをお勧めするパターンです。

using (var instanceName = new DisposableClass())
{
    // Your code here
}

シンプルで、クリーンで、破損している WCF プロキシ クラスを除いて、すべてに対して機能します。それらについては、http://www.iservicedirectional.com/blog/post/Indisposable+-+WCF+Gotcha+1.aspxを参照してください。

于 2009-04-15T17:08:17.607 に答える
2

メソッドが終了すると、Font オブジェクトは破棄されませんか?

いいえ、参照されなくなり、ガベージ コレクションの対象になります。他の何か (たとえば、別のデータ構造に保持されている参照) が参照を保持していない限り。

または、メソッドが終了した後、別のときに Dispose メソッドが実行されますか?

はい、メソッドが終了してからかなりの時間がかかる可能性がある多くのメモリを割り当てないプロセスで。

ガベージ コレクションは本質的に非同期で怠惰であるため、メモリがあまり制限されていない場合は、メモリを確実に解放する優れた方法になります。しかし、他のほとんどのリソースには不十分です。

于 2009-04-15T16:48:58.387 に答える
0

これらは、オブジェクトに対してクリーンアップ コードを決定論的に、例外に関係なく呼び出す必要がある場合に役立ちます (usingステートメントは実際には単なる であるためtry/finally)。

ほとんどの場合、管理されていないリソースをクリーンアップするために使用されますが、必要に応じて使用できます。

于 2009-04-15T16:38:48.347 に答える
0

これは、try-catch-finally ブロックと Dispose メソッドの呼び出しの上にある純粋な構文糖衣です。インスタンス変数を渡すことができるため、レキシカルスコープを定義する必要さえありません。基本的に、コードがよりクリーンになり、保守が容易になります。

于 2009-04-15T16:41:55.627 に答える
0

Dispose は、そのコンストラクトによって明示的に呼び出されるため、using ステートメントを終了するときに呼び出されます。変数がスコープ外に出たとき (メソッドを終了したとき)、dispose メソッドは明示的に呼び出されません。

そのように見える動作は、通常、IDisposable を実装するものはクラスのデストラクタで Dispose メソッドも呼び出し、変数がスコープ外になった直後にデストラクタが呼び出される可能性がありますが、保証されていません。デストラクタは、ガベージ コレクタによって呼び出されます。

于 2009-04-15T16:42:21.380 に答える
0

私は次のようにそれらを使用するのが好きです:

    static public void AddSampleData(String name)
    {
        String CreateScript = GetScript(String.Format("SampleData_{0}", name));
        using (IDbConnection MyConnection = GetConnection())
        {
            MyConnection.Open();
            IDbCommand MyCommand = MyConnection.CreateCommand();
            foreach (String SqlScriptLine in CreateScript.Split(';'))
            {
                String CleanedString = SqlScriptLine.Replace(";", "").Trim();
                if (CleanedString.Length == 0)
                    continue;

                MyCommand.CommandText = CleanedString;
                int Result = MyCommand.ExecuteNonQuery();
            }
        }
    }

エラーチェックコードを配置したくない場合に最適です。コードをクリーンアップしてエラーを渡します。別の方法は次のようになります。

    static public void AddSampleData(String name)
    {
        String CreateScript = GetScript(String.Format("SampleData_{0}", name));

        IDbConnection MyConnection = null;
        try
        {
            IDbConnection MyConnection = GetConnection();
            MyConnection.Open();
            IDbCommand MyCommand = MyConnection.CreateCommand();
            foreach (String SqlScriptLine in CreateScript.Split(';'))
            {
                String CleanedString = SqlScriptLine.Replace(";", "").Trim();
                if (CleanedString.Length == 0)
                    continue;

                MyCommand.CommandText = CleanedString;
                int Result = MyCommand.ExecuteNonQuery();
            }
        }
        finally
        {
            if (MyConnection != null
                && MyConnection.State == ConnectionState.Open)
                MyConnection.Close();
        }
    }

率直に言って、どちらの方法が読みやすいですか? フォームと同じこと:

    public void ChangeConfig()
    {
        using (ConfigForm MyForm = new ConfigForm())
        {
            DialogResult ConfigResult = MyForm.ShowDialog();
            if (ConfigResult == DialogResult.OK)
                SaveConfig();
        }

        ConfigForm MyForm = new ConfigForm();
        DialogResult ConfigResult = MyForm.ShowDialog();
        MyForm.Dispose();
        if (ConfigResult == DialogResult.OK)
            SaveConfig();
    }
于 2009-04-15T16:43:43.813 に答える
0

using決定論的対非決定論的、および内部での作業がどのように正しいかについてのすべての答え。

ただし、特定のサンプルを選択するには、ほぼすべてのSystem.Drawing (GDI+ ラッパー) オブジェクトもアンマネージ メモリへの参照を保持していることを忘れないでください。そのため、それらを適切に破棄せずに広範囲に使用すると問題が発生する可能性があります (using最も簡単な方法はどこですか)。 )。

于 2009-04-15T16:50:49.987 に答える