我习惯使用“使用”语句来实现一些范围锁定模式。
示例:
ReaderWriterLockSlim _storageLocker
using (_storageLocker.LockRead())
{
// do suff
}
在此示例中,扩展方法LockRead创建一个特定的IDisposable对象,该对象将在构造时锁定并在释放时释放。
/// <summary>
/// Scope lock pattern that lock the current <see cref="ReaderWriterLockSlim"/> in read mode
/// </summary>
public static IDisposable LockRead(this ReaderWriterLockSlim locker, TimeSpan timeout = default(TimeSpan))
{
if (timeout == default(TimeSpan))
timeout = s_defaultTimeout;
var isLocked = locker.TryEnterReadLock(timeout);
if (isLocked)
return new ScopeLockAction<ReaderWriterLockSlim>(l => l.ExitReadLock(), locker);
return Disposable.Disposed;
}
此模式比try/Finally
有用且更干净,但可悲的是,每次锁定时都会创建一个新实例。
ScopeLockAction
正确地实现了IDispose
模式,并调用了GC.SuppressFinalizer()
以稍微优化回收率。
我知道.NET garbadge收集器实现了某种回收机制,使他可以为将来的相同类型实例重用分配的空间。
我的问题是:
当您有一个固定大小的小型实例,该实例通常会创建和处理,并且仅与using语句一起使用(这意味着没有装箱)时,使用class
或struct
?
有什么区别吗?
是否可以通知Garbadge收集器它可以为另一个相同类型的实例回收实例空间?
答案 0 :(得分:0)
来自帖子answer中的What are the uses of "using" in C#:
“ using”语句的原因是确保该对象是 一旦超出范围就立即处置,不需要 明确的代码以确保发生这种情况。
结构是值类型,类是引用类型,我认为,使用“ using”语句并不重要,因为一旦超出范围,它就会被销毁。
您可以在Finalize/Dispose pattern in C#
答案 1 :(得分:0)
因此代码将如下所示,请注意,当TryEnterReadLock返回false时,您必须检查大小写:
var _storageLocker = new ReaderWriterLockSlim();
using (var lockContext =new ReadLockContext(_storageLocker))
{
if (lockContext.IsAcquired)
{
}
}
public struct ReadLockContext : IDisposable
{
private readonly ReaderWriterLockSlim locker;
public ReadLockContext(ReaderWriterLockSlim locker, TimeSpan timeout = default(TimeSpan))
{
if (timeout == default(TimeSpan))
timeout = TimeSpan.FromMilliseconds(-1);
if (locker.TryEnterReadLock(timeout))
this.locker = locker;
else
this.locker = null;
}
public bool IsAcquired => locker != null;
public void Dispose()
{
locker?.ExitReadLock();
}
}