C# 返回IDisposable对象并仅在异常时处理的最佳方法?
我一直在寻找这个问题的答案,但我无法真正找到我正在实施的确切案例。我希望在方法中返回IDisposable对象,而不在同一方法中处理/关闭。但我只想在引发异常时处理该对象。在这种情况下,最好的处理方法是什么?以下是我目前处理这个案件的方式C# 返回IDisposable对象并仅在异常时处理的最佳方法?,c#,exception,exception-handling,idisposable,C#,Exception,Exception Handling,Idisposable,我一直在寻找这个问题的答案,但我无法真正找到我正在实施的确切案例。我希望在方法中返回IDisposable对象,而不在同一方法中处理/关闭。但我只想在引发异常时处理该对象。在这种情况下,最好的处理方法是什么?以下是我目前处理这个案件的方式 public DisposableObject GetObject() { DisposableObject object = null; try { object = new DisposableObject();
public DisposableObject GetObject()
{
DisposableObject object = null;
try
{
object = new DisposableObject();
object.Open();
}
catch
{
if (object != null)
{
object.Close();
}
throw;
}
return object;
}
从上述方法创建的对象将被其他类似的方法使用和处理
public void OtherMethod()
{
using(var object2 = GetObject())
{
DoSomethingWithObject2(object2);
}
}
在这种情况下还有其他选择吗?我想我宁愿把打开和关闭连接的所有责任推给该对象的用户,而不是工厂 在您展示的当前方法中,如果不创建实际连接,就无法创建实例(例如测试)。此外,该方法是否不透明,因为另一个人不会假定连接已打开 我发布的方法使代码用户能够更轻松地处理打开DisposableObject时可能发生的错误
public DisposableObject GetObject() {
return new DisposableObject();
}
public void OtherMethod() {
using (DisposableObject o = GetObject()) {
try {
o.Open();
} catch (Exception ex) {
// Log(ex);
} finally {
// If not called within the dispose function.
o.Close();
}
}
}
不过,如果你想处理开口,你的方法是可以的。不过,我想更改一些小细节:
public DisposableObject GetObject() {
var o = new DisposableObject();
try {
o.Open();
return o;
} catch (Exception ex) {
o.Dispose(); // o.Close is called within.
throw ex;
}
}
我想我宁愿把打开和关闭连接的所有责任推给这个对象的用户,而不是工厂 在您展示的当前方法中,如果不创建实际连接,就无法创建实例(例如测试)。此外,该方法是否不透明,因为另一个人不会假定连接已打开 我发布的方法使代码用户能够更轻松地处理打开DisposableObject时可能发生的错误
public DisposableObject GetObject() {
return new DisposableObject();
}
public void OtherMethod() {
using (DisposableObject o = GetObject()) {
try {
o.Open();
} catch (Exception ex) {
// Log(ex);
} finally {
// If not called within the dispose function.
o.Close();
}
}
}
不过,如果你想处理开口,你的方法是可以的。不过,我想更改一些小细节:
public DisposableObject GetObject() {
var o = new DisposableObject();
try {
o.Open();
return o;
} catch (Exception ex) {
o.Dispose(); // o.Close is called within.
throw ex;
}
}
正如Morton所说,问题在于在工厂方法中对
DisposableObject
实例调用Open
,但我不同意相应的解决方案
真正的问题是,Open
是一个泄漏的抽象。为什么我要实例化一个无效的实例?当我想要一个文件流时,我调用file.Open(…)
,我不会实例化一个新的流
并调用OpenFile(…)
。这将迫使我知道如何打开该文件,并完全违背工厂方法的目的(是的,file.open
是流
实例的工厂方法)
所以当我读一个文件时,我是这样读的:
using (var stream = File.Open("myFile.text", FileMode.Open))
using (var reader = new StreamReader(stream))
{
var content = reader.ReadToEnd();
Console.WriteLine(content);
}
如果文件无法正确打开,我不必担心如何关闭该文件。事实上,如果Open
调用抛出异常,那么using
语句甚至不能调用stream
上的Dispose()
,因为流还没有被分配,执行流甚至还没有进入using
语句的块范围
public class Program
{
public void Main()
{
try
{
using (var obj = MyObj.Create())
{
// everything is already in a valid state.
var message = obj.ReadMessage();
Console.WriteLine(message);
}
}
catch (Exception ex)
{
// If the factory succeeded, the using statement did the cleanup.
// if the factory failed, the factory took care of the cleanup.
Console.WriteLine(ex.Message);
}
}
}
及
正如Morton所说,问题在于在工厂方法中对
DisposableObject
实例调用Open
,但我不同意相应的解决方案
真正的问题是,Open
是一个泄漏的抽象。为什么我要实例化一个无效的实例?当我想要一个文件流时,我调用file.Open(…)
,我不会实例化一个新的流
并调用OpenFile(…)
。这将迫使我知道如何打开该文件,并完全违背工厂方法的目的(是的,file.open
是流
实例的工厂方法)
所以当我读一个文件时,我是这样读的:
using (var stream = File.Open("myFile.text", FileMode.Open))
using (var reader = new StreamReader(stream))
{
var content = reader.ReadToEnd();
Console.WriteLine(content);
}
如果文件无法正确打开,我不必担心如何关闭该文件。事实上,如果Open
调用抛出异常,那么using
语句甚至不能调用stream
上的Dispose()
,因为流还没有被分配,执行流甚至还没有进入using
语句的块范围
public class Program
{
public void Main()
{
try
{
using (var obj = MyObj.Create())
{
// everything is already in a valid state.
var message = obj.ReadMessage();
Console.WriteLine(message);
}
}
catch (Exception ex)
{
// If the factory succeeded, the using statement did the cleanup.
// if the factory failed, the factory took care of the cleanup.
Console.WriteLine(ex.Message);
}
}
}
及
您不应该在
catch
中调用object.Dispose()
?我似乎不明白为什么会有人想这样做。另外,删除该抛出将允许它返回,但不会处理异常。您能提供一个真实的示例吗?这段代码甚至不是有效的C#。如果我们知道你想要完成什么,而不是你试图如何实现它,那么提供一个答案可能会更容易。这看起来很奇怪。一个真实的单词示例会很棒。你不应该在catch
中调用object.Dispose()
?我似乎不明白为什么有人想这样做。另外,删除该抛出将允许它返回,但不会处理异常。您能提供一个真实的示例吗?这段代码甚至不是有效的C#。如果我们知道你想要完成什么,而不是你试图如何实现它,那么提供一个答案可能会更容易。这看起来很奇怪。一个真实的单词示例会很棒。o
以无效状态存在,而工厂方法正是这种情况的原因。您的解决方案是反模式。o
以无效状态存在,而工厂方法正是这种情况的原因。您的解决方案是反模式的。