Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 返回IDisposable对象并仅在异常时处理的最佳方法?_C#_Exception_Exception Handling_Idisposable - Fatal编程技术网

C# 返回IDisposable对象并仅在异常时处理的最佳方法?

C# 返回IDisposable对象并仅在异常时处理的最佳方法?,c#,exception,exception-handling,idisposable,C#,Exception,Exception Handling,Idisposable,我一直在寻找这个问题的答案,但我无法真正找到我正在实施的确切案例。我希望在方法中返回IDisposable对象,而不在同一方法中处理/关闭。但我只想在引发异常时处理该对象。在这种情况下,最好的处理方法是什么?以下是我目前处理这个案件的方式 public DisposableObject GetObject() { DisposableObject object = null; try { object = new DisposableObject();

我一直在寻找这个问题的答案,但我无法真正找到我正在实施的确切案例。我希望在方法中返回IDisposable对象,而不在同一方法中处理/关闭。但我只想在引发异常时处理该对象。在这种情况下,最好的处理方法是什么?以下是我目前处理这个案件的方式

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
以无效状态存在,而工厂方法正是这种情况的原因。您的解决方案是反模式的。