“使用”的语句VS“尝试终于”语句、VS

2023-09-02 11:45:55 作者:默默丶做坏事

我有一大堆,我现在要使用读/写锁的特性。我可以实现他们要么用尝试终于使用条款。

尝试终于我将收购前的锁尝试,并释放在最后。在使用子句,我将创建一个类,获得在其构造锁,并释放在其Dispose方法。

我使用的读/写锁在了很多地方,所以我一直在寻找那可能比更简洁的尝试终于办法。我有兴趣听取为什么单向的一些想法可能不被推荐的,或者为什么人们可能会比另一种更好。

方法1(尝试终于):

 静态ReaderWriterLock rwlMyLock_m =新ReaderWriterLock();
私营的DateTime dtMyDateTime_m
公开日期时间MyDateTime
{
    得到
    {
        rwlMyLock_m .AcquireReaderLock(0);
        尝试
        {
            返回dtMyDateTime_m
        }
        最后
        {
            rwlMyLock_m .ReleaseReaderLock();
        }
    }
    组
    {
        rwlMyLock_m .AcquireWriterLock(0);
        尝试
        {
            dtMyDateTime_m =价值;
        }
        最后
        {
            rwlMyLock_m .ReleaseWriterLock();
        }
    }
}
 

方法2:

 静态ReaderWriterLock rwlMyLock_m =新ReaderWriterLock();
私营的DateTime dtMyDateTime_m
公开日期时间MyDateTime
{
    得到
    {
        使用(新ReadLock(rwlMyLock_m))
        {
            返回dtMyDateTime_m;
        }
    }
    组
    {
        使用(新WriteLock(rwlMyLock_m))
        {
            dtMyDateTime_m =价值;
        }
    }
}

公共类ReadLock:IDisposable的
{
    私人ReaderWriterLock RWL;
    公共ReadLock(ReaderWriterLock RWL)
    {
        this.rwl = RWL;
        rwl.AcquireReaderLock(0);
    }

    公共无效的Dispose()
    {
        rwl.ReleaseReaderLock();
    }
}

公共类WriteLock:IDisposable的
{
    私人ReaderWriterLock RWL;
    公共WriteLock(ReaderWriterLock RWL)
    {
        this.rwl = RWL;
        rwl.AcquireWriterLock(0);
    }

    公共无效的Dispose()
    {
        rwl.ReleaseWriterLock();
    }
}
 
7年了,我终于敢对她说出这句话

解决方案

从MSDN, using语句(C#参考)

  

using语句确保即使当你调用对象的方法发生了异常的调用Dispose。您可以通过将对象try块中,然后调用Dispose在finally块达到同样的效果;其实,这是怎样的using语句是由编译器翻译。在code例如前面扩展到在编译时以下code(注额外的花括号创建该对象的范围有限):

  {
  字体font1 =新的字体(宋体,10.0f);
  尝试
  {
    字节字符集= font1.GdiCharSet;
  }
  最后
  {
    如果(font1!= NULL)
      ((IDisposable接口)font1).Dispose();
  }
}
 

因此​​,基本上,这是相同的code,但有一个很好的自动空支票和一个额外的范围,您的变量。该文件还指出,它确保正确使用IDisposable的对象,所以你还不如获得任何模糊的情况下,在未来甚至更好的框架的支持。

所以去选择2。

具有可变的一个范围内的的是立即结束之后,它不再需要也是一个加号。

I've got a bunch of properties which I am going to use read/write locks on. I can implement them either with a try finally or a using clause.

In the try finally I would acquire the lock before the try, and release in the finally. In the using clause, I would create a class which acquires the lock in its constructor, and releases in its Dispose method.

I'm using read/write locks in a lot of places, so I've been looking for ways that might be more concise than try finally. I'm interested in hearing some ideas on why one way may not be recommended, or why one might be better than another.

Method 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();
        }
    }
}

Method 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();
    }
}

解决方案

From MSDN, using Statement (C# Reference)

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler. The code example earlier expands to the following code at compile time (note the extra curly braces to create the limited scope for the object):

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

So basically, it is the same code but with a nice automatic null-checks and an extra scope for your variable. The documentation also states that it "ensures the correct use of IDisposable object" so you might as well gets even better framework support for any obscure cases in the future.

So go with option 2.

Having the variable inside a scope that ends immediately after it's no longer needed is also a plus.