8

usingこのステートメントは、開いているファイルやデータベース接続など、タイムリーにクリーンアップしたいリソースに非常に適していることは誰もが知っています。

Dispose()リソースのクリーンアップがメソッドの目的ではなく、以前の状態にリセットする場合に、ステートメントを使用するのが良いことと見なされるかどうか疑問に思っていました。

たとえば、かなりの時間がかかり、Cursor を待機状態に変更するプロシージャを using ステートメントでラップできるようにするクラスです。

class CursorHelper : IDisposable
{
   readonly Cursor _previousState;
   public CursorHelper(Cursor newState)
   {
      _previousState = Cursor.Current;
      Cursor.Current = newState;
   }

   public void Dispose()
   {
      Cursor.Current = _previousState;
   }
}

その後、完了時に Cursor を元に戻すことを心配することなく、クラスをそのまま使用できます。

public void TimeIntensiveMethod()
{
   using (CursorHelper ch = new CursorHelper(Cursors.WaitCursor))
   {
      // something that takes a long time to complete
   }
}

usingこれは、ステートメントの適切な使用法ですか?

4

5 に答える 5

4

私はこれに反対であり、虐待であると信じています。また、C++ の RAII はひどい考えだと思います。私は両方の立場で少数派であることを認識しています。

この質問は重複しています。これが using ステートメントの不当な乱用であると私が考える理由の詳細については、https ://stackoverflow.com/a/2103158/88656 を参照してください。

于 2013-05-29T15:12:41.230 に答える
2

usingいいえ、それはand/orの適切な使用ではありませんDispose。このパターンには非常に明確な用途 ( 「割り当てられたリソースを解放するメソッドを定義します。」 ) がありますが、そうではありません。このコードを使用する将来の開発者は、そのような悪を正当化する軽蔑の目でそれを見るでしょう。

このの動作が必要な場合は、イベントを実装して公開し、必要に応じてコードを呼び出してそれらをサブスクライブし、カーソルを管理できます。そうでない場合、カーソルは一般的なパラメーターで管理できBeginEndメソッドを使用することもできます (ただし、このような命名規則は一般にメソッドの非同期実装用に予約されているため、写真が得られます)-この方法でハッキングしても、実際には何も得られません.

于 2013-05-29T13:48:15.760 に答える
-1

オブジェクトを単に処分する以外の方法で using-Disposable のものを使用することは理にかなっていると思います。もちろん、それは文脈と用途に依存します。より読みやすいコードにつながる場合は、問題ありません。

次のような作業単位とリポジトリパターンの実装で使用しました。

public class UnitOfWork: IDisposable  {
    // this is thread-safe in actual implementation
    private static Stack<UnitOfWork> _uowStack = new Stack<UnitOfWork>();
    public static UnitOfWork Current {get { return _uowStack.Peek(); }} 

    public UnitOfWork() {
        _uowStack.Push(this);
    }

    public void Dispose() {
        _ouwStack.Pop();
    }

    public void SaveChanges() {
        // do some db operations
    }
}

public class Repository {
    public void DoSomething(Entity entity) {
        // Do Some db operations         

        UnitOfWork.Current.SaveChanges();
    }
}

この実装により、ネストされた操作がパラメーターを渡さずに対応する UnitOfWork を使用することが保証されます。使い方はこんな感じ。

using (new UnitOfWork()) 
{
    var repo1 = new UserRepository();
    // Do some user operation

    using (new UnitOfWork())  
    {
         var repo2 = new AccountingRepository();
         // do some accounting
    }

    var repo3 = new CrmRepository();
    // do some crm operations
}

このサンプルでは、​​repo1 と repo3 は同じ UnitOfWork を使用し、repo2 は別のリポジトリを使用します。読者が読むのは「新しい作業単位の使用」であり、それは非常に理にかなっています。

于 2013-05-29T13:48:30.997 に答える