1. ホーム
  2. c#

[解決済み] using文とtry finally文の比較

2023-06-12 23:50:46

質問

読み取り/書き込みロックを使用する予定のプロパティの束があります。私は、それらを try finally または using 節を使用します。

では try finally の前にロックを取得することになりますね。 try で解放します。 finally . で using 節では、コンストラクタでロックを取得し、Disposeメソッドでロックを解放するクラスを作成します。

私は多くの場所で読み取り/書き込みロックを使用しているため、以下の方法よりも簡潔な方法を探していました。 try finally . ある方法が推奨されない理由や、ある方法が他の方法よりも優れている理由について、いくつかのアイデアを聞いてみたいと思っています。

方法1 ( try finally ):

static ReaderWriterLock rwlMyLock_m  = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
    get
    {
        rwlMyLock_m .AcquireReaderLock(0);
        try
        {
            return dtMyDateTime_m
        }
        finally
        {
            rwlMyLock_m .ReleaseReaderLock();
        }
    }
    set
    {
        rwlMyLock_m .AcquireWriterLock(0);
        try
        {
            dtMyDateTime_m = value;
        }
        finally
        {
            rwlMyLock_m .ReleaseWriterLock();
        }
    }
}

方法2

static ReaderWriterLock rwlMyLock_m  = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
    get
    {
        using (new ReadLock(rwlMyLock_m))
        {
            return dtMyDateTime_m;
        }
    }
    set
    {
        using (new WriteLock(rwlMyLock_m))
        {
            dtMyDateTime_m = value;
        }
    }
}

public class ReadLock : IDisposable
{
    private ReaderWriterLock rwl;
    public ReadLock(ReaderWriterLock rwl)
    {
        this.rwl = rwl;
        rwl.AcquireReaderLock(0);
    }

    public void Dispose()
    {
        rwl.ReleaseReaderLock();
    }
}

public class WriteLock : IDisposable
{
    private ReaderWriterLock rwl;
    public WriteLock(ReaderWriterLock rwl)
    {
        this.rwl = rwl;
        rwl.AcquireWriterLock(0);
    }

    public void Dispose()
    {
        rwl.ReleaseWriterLock();
    }
}

どのように解決するのですか?

MSDNより。 usingステートメント(C#リファレンス)

<ブロッククオート

usingステートメントは、オブジェクトのメソッドを呼び出している間に例外が発生した場合でも、Disposeが呼び出されることを保証します。オブジェクトを try ブロック内に置き、finally ブロック内で Dispose を呼び出すことで同じ結果を得ることができます。実際、これは using 文がコンパイラによって翻訳される方法です。先ほどのコード例は、コンパイル時に次のようなコードに展開されます (オブジェクトの限定的なスコープを作成するために中括弧が追加されていることに注意してください)。

{
  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }
}

ですから、基本的には は同じコードですが、自動的なヌルチェックと変数のための余分なスコープを備えています。 . ドキュメントには、IDisposableオブジェクトの正しい使用を保証するとも書かれています(quot; ensure the correct use of IDisposable object" so you might as well gets even better framework support for any obscure cases in the future.

というわけで、2.を選択します。

変数 がスコープ内にあること の中にあって、それが不要になったらすぐに終了することもプラスです。