【问题标题】:Is is right to return a method inside a "using(object that implements iDisposable)" statment? [duplicate]在“使用(实现 iDisposable 的对象)”语句中返回方法是否正确? [复制]
【发布时间】:2012-12-26 23:41:47
【问题描述】:

可能重复:
If I return a value inside a using block in a method, does the using dispose of the object before the return?

我有这个代码(简化):

bool method1()
{
      using (OleDbConnection con = new OleDbConnection(connString))
            {
                bool b = false;

                try
                {
                    con.Open();
                    b = true;

                }
                catch (Exception)
                {
                    b = false;
                }
                finally
                {
                    con.Close();
                    return b;
                }                
            }
}

我在“使用”语句的右大括号之前返回。我的对象“con”是否仍然被 Disposed?使用以下代码更好吗?:

bool method1()
{
      bool b = false;
      using (OleDbConnection con = new OleDbConnection(connString))
            {
                try
                {
                    con.Open();
                    b = true;

                }
                catch (Exception)
                {
                    b = false;
                }
                finally
                {
                    con.Close();                    
                }                
            }

        return b;
}

【问题讨论】:

    标签: c# .net idisposable using


    【解决方案1】:

    两个代码段之间没有区别; con 对象将在两个示例中被释放。

    【讨论】:

      【解决方案2】:

      using 语句的全部意义在于它自动处理对象,即使从 using 块中抛出未处理的异常也是如此。

      因此,一旦您的代码退出 using 块,无论是返回还是其他方式,我们都会处理“使用”的对象。

      【讨论】:

      • 还要注意,因此,您不需要像以前那样显式调用Close()。如果你反编译 OleDbConnection 你会看到 Dispose 调用了 Close
      • @Rhumborl:感谢您的提示。我来自一个不受管理的世界(VB6 C++),所以我很容易对垃圾收集器的东西感到困惑。
      • Y3L1NNa - 至少使用 using 可以获得 +1。忘掉你对 VB 和 C++ 的大部分了解,让 C#/NET 自成一派。稍后,一旦您习惯了“托管代码、托管数据”范式,您就可以比较和欣赏 VB 和 C++。快乐编码
      【解决方案3】:

      在第一个示例中,您设置了一个临时变量并将其返回。

      关于 finally 中的返回:编译后发生的事情是你分支到方法的末尾,然后返回一个临时变量。

      例如结果是完全一样的。为了清楚起见,我个人更喜欢第一个,因为它更准确地类似于发生的事情。

      【讨论】:

        【解决方案4】:

        由于 .NET 自动处理对象的魔法,在 using 语句期间返回是完全安全的。整个想法是你不必考虑如何退出 using 块,你只知道当你离开它时,对象将被正确处理。因此,您的示例可以简化为:

        bool method1()
        {
            using (OleDbConnection con = new OleDbConnection(connString))
                {
                    try
                    {
                        con.Open();
                        return true;
                    }
                    catch (Exception)
                    {
                        return false;
                    }          
            }
        }
        

        con.Close() 可以被删除,也可以被处理自动调用。

        如果您想了解幕后发生的事情,请查看 this

        【讨论】:

          【解决方案5】:

          using 扩展为更复杂的附加 if 语句,如

          OleDbConnection con = new OleDbConnection(connString)
          try
          {
              con.Open();
          }
          finally
          {
              // Check for a null resource.
              if (con != null)
                  // Call the object's Dispose method.
                  ((IDisposable)con).Dispose();
          }  
          

          因此,在您的示例中,您可能会在 finally 块中获得 NullReferenceException

          所以如果你想返回操作和Dispose和object的状态,我建议使用这段代码sn -p

          using(OleDbConnection con = new OleDbConnection(connString))
          {
              try
              {
                  con.Open();
                  return true;
              }catch(OleDbException ex)
              {
                  //log error
                  return false;
              }
          }
          

          【讨论】:

          • 我选择了这个作为答案,因为它对我的具体情况最准确,而且我没有注意到在某些情况下我会得到 NullReferenceException。谢谢!
          • 请注意不要在 catch 块中捕获 Exception。只需捕获特定的OleDbException 异常。但是在这种情况下,我会考虑制作方法void,而不是返回一些标志。它对例外情况进行例外处理,而不是对正常的逻辑流程。
          猜你喜欢
          • 2015-09-15
          • 2010-11-05
          • 1970-01-01
          • 2020-03-05
          • 1970-01-01
          • 2011-05-02
          • 2016-08-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多