C# 如何正确处理一次性对象构造函数中的异常

C# 如何正确处理一次性对象构造函数中的异常,c#,exception,dispose,finalizer,C#,Exception,Dispose,Finalizer,假设我有一个没有非托管资源的对象,我不需要或不想使用终结器: public sealed类SealedDisposableClass:IDisposable { 私有只读信号量lim _readLock=新信号量lim(1,1); 私有只读信号量lim_writeLock=新信号量lim(1,1); 私人住宅被出售; 公共空间处置() { 如果(_isDisposed) 回来 _readLock.Dispose(); _writeLock.Dispose(); _isDisposed=true;

假设我有一个没有非托管资源的对象,我不需要或不想使用终结器:

public sealed类SealedDisposableClass:IDisposable
{
私有只读信号量lim _readLock=新信号量lim(1,1);
私有只读信号量lim_writeLock=新信号量lim(1,1);
私人住宅被出售;
公共空间处置()
{
如果(_isDisposed)
回来
_readLock.Dispose();
_writeLock.Dispose();
_isDisposed=true;
}
}
现在让我们假设一种假设情况,即信号量lim的构造函数有时会抛出异常。假设我们创建SealedDisposableClass的新实例时,编译器决定按以下顺序初始化字段:

_readLock = new SemaphoreSlim(1, 1);
_writeLock = new SemaphoreSlim(1, 1);
现在让我们假设第一行成功执行,并在_readLock成员中存储一个托管对象_readLock引用。让我们假设第二行异常失败。所以我们没有得到writeLock引用。我们甚至没有得到SealedDisposableClass实例。一切都在建筑上。然而,内存中的某个地方创建了一个SemaphoreSlim实例

如何妥善处理这种情况??我应该总是在构造函数中尝试/捕获吗?我是否应该为信号量lim的偶数添加try/catch(或者创建信号量lim对象总是安全的?)。有没有更优雅的方法来处理这个问题


谢谢。

您可以通过构造函数中的try/catch来处理此问题。如果在处置内部对象之前检查它们是否存在,则可以使用dispose方法进行清理

public sealed类SealedDisposableClass:IDisposable
{
私有只读信号量lim\u readLock;
私有只读信号量limu writeLock;
私有bool_isDisposed=false;
公共密封DisposableClass()
{
尝试
{
_readLock=新信号量lim(1,1);
_writeLock=新信号量lim(1,1);
}
接住
{
处置();
投
}
}
公共空间处置()
{
如果(_isDisposed)
回来
_readLock?.Dispose();
_writeLock?.Dispose();
_isDisposed=true;
}
}
或者,您可以执行两步构造,首先实例化对象,然后在实际使用之前对其进行初始化。这在一些地方很常见,尽管我觉得不太方便使用

public void Initialize()
{
_readLock=新信号量lim(1,1);
_writeLock=新信号量lim(1,1);
}
...
使用(var x=new SealedDisposableClass())
{
x、 初始化();
}

如果没有人持有对信号量lim的引用,它将被垃圾收集。因此GC将在一段时间后调用Dispose,我不需要处理这个问题,对吗?谢谢这是一场极其严重的灾难。让事情变得更糟的唯一办法就是设法处理它。永远不要那样做。