5

の違いを理解したい

public DataTable ExectNonActQuery(string spname, SqlCommand command)
{
    using (DataTable dt = new DataTable())
    {
        cmd = command;
        cmd.Connection = GetConnection();
        cmd.CommandText = spname;
        cmd.CommandType = CommandType.StoredProcedure;
        da.SelectCommand = cmd;
        da.Fill(dt);
        return (dt);
    }
}

public DataTable ExectNonActQuery(string spname, SqlCommand command)
{
    DataTable dt = new DataTable();
    cmd = command;
    cmd.Connection = GetConnection();
    cmd.CommandText = spname;
    cmd.CommandType = CommandType.StoredProcedure;
    da.SelectCommand = cmd;
    da.Fill(dt);
    return (dt);
    }
}

このように直接作成するのではなく、「使用」を使用して新しいオブジェクトを作成する利点を実際に理解したい

DataTable dt = new DataTable();
4

6 に答える 6

16

最初の例は正しくありません。終了時に内部で宣言された変数で呼び出されるusing(var ...)ことを保証します。したがって、最初の例は破棄されたオブジェクトを返しますがこれはほぼ間違いなく間違っています。IDisposable.Disposeusing

一般に、usingブロックはこれとほぼ同等です。

var x = new MyDisposable();
try {
    // Do something with x
} finally {
    x.Dispose();
}

これは C# では非常に一般的なパターンであるため、便宜上、特別な構文が用意されています。

于 2012-04-28T16:22:59.873 に答える
11

usingオブジェクトが using ステートメントの最後で破棄されることを保証します

代わりに .Dispose() を手動で呼び出すこともできますが、 をusing使用すると、例外をスローしても破棄されます

また、.Dispose を呼び出すのを忘れたり、Dispose を呼び出す前に変数を再割り当てしたりするなど、自分の間違いからも保護されます。

それはすべてドキュメントにあります:

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

編集:また、dasblinkenlightが他の回答で説明しているように、関数からオブジェクトを返すときにオブジェクトを破棄するのは悪い考えです

ただし、DataTable、DataSet、および DataView の特殊なケースでは、これらのオブジェクトを破棄する必要はありません。したがって、この特定の例では、DataTable が IDisposable であることを無視しても安全です。さらに、DataTable の .Dispose() メソッドは明示的に何もしない (ファイナライズが抑制される) ため、破棄されたオブジェクトを返すにもかかわらず、最初の例は実際には機能するはずです。

DataSet と DataTable を Dispose() する必要がありますか? を参照してください。

したがって、あなたの特定の例では、実際の違いはおそらくゼロです。

実用的な場合は、IDisposables を Using ステートメントでラップすることをお勧めします。(オブジェクトを関数内で構築し、その関数の外でアクセスする必要がある場合、これは不可能です。)

于 2012-04-28T16:20:44.773 に答える
4
using (DataTable dt = new DataTable())

に等しい

DataTable dt = new DataTable();
try
{
}
finally 
{
    if(dt != null)
        dt.Dispose()
}

したがって、この場合、例外がスローされると、データテーブル オブジェクトが破棄されます。あなたのケースでは、ファイナライザーが DataTable クラスに定義されている場合、ガベージコレクターがそれを収集する場合にのみ、それを使用せずに破棄されます

于 2012-04-28T16:25:05.413 に答える
1

msdn から、

1 つまたは複数のオブジェクトが破棄される範囲外のスコープを定義します。

使用したオブジェクトのメモリ/リソースの破棄について心配する必要はありません。using ステートメントがそれを処理します。usingusing ブロック内で定義された変数は、コントロールがステートメントの外側のブロック (スコープ)を出ると、自動的に破棄されます。

典型的な例は、SQL 接続です。通常、Close メソッドを呼び出して、トランザクション後に明示的に接続を閉じる必要があります。しかし、using statmenet を使用すれば、その心配はありません。

CLR は通常、CLR がガベージ コレクションの実行を決定するたびに、メモリの解放を行います。このusingステートメントを使用することで、手動で使用したメモリ/リソースを解放しています。

于 2012-04-28T16:24:07.143 に答える
1

usingステートメントを使用する場合、異なる方法でオブジェクトを作成していません。

using ステートメントは、IDisposable を継承するオブジェクトをラップするだけです。入力するとき

using (DataTable dt = new DataTable()) { }

from の戻り値DataTable dt = new DataTable()は、using ステートメントに入る dt への参照です。

したがって、これは次のように書くこともできます

DataTable dt = new DataTable();
using (dt) { }

using ステートメントの理由は、他の回答で述べられているように、変数によって保持されているリソースを、ガベージ コレクターが通常解放する前に解放できるためです。

于 2012-04-28T16:27:25.787 に答える
1

using で型を宣言するには、オブジェクトの定義されたスコープが終了すると、型で定義された破棄されたメソッドの助けを借りてオブジェクトがクリーンアップされるように、型に IDisposable を実装する必要があります。

定数を値に変換するのと同じように、コンパイラ自体が using を try..Finally ステートメントに変換するため、これは非常に興味深いことです。したがって、 & try..finally を使用する動作は、ランタイム全体で同じです:)。

詳細を理解するには、次のリンクを使用してください: http://www.codeproject.com/Articles/6564/Understanding-the-using-statement-in-C

お役に立てば幸いです。

于 2012-04-28T18:34:45.017 に答える