【问题标题】:Are there any side effects of returning from inside a using() statement?从 using() 语句内部返回是否有任何副作用?
【发布时间】:2011-01-23 02:47:12
【问题描述】:

inside 获取 DataContext 的 using 语句返回方法值似乎总是正常,如下所示:

public static Transaction GetMostRecentTransaction(int singleId)
{
    using (var db = new DataClasses1DataContext())
    {
        var transaction = (from t in db.Transactions
                              orderby t.WhenCreated descending
                              where t.Id == singleId
                              select t).SingleOrDefault();
        return transaction;
    }
}

但我总是觉得我应该在打破使用括号之前关闭一些东西,例如通过定义事务before using 语句,得到它的值inside 括号,然后返回after 括号。

在使用方括号之外定义和返回变量是更好的做法还是以任何方式节省资源?

【问题讨论】:

  • 查看通用 IL 的变体可能会很有趣。我怀疑生成的 IL 几乎没有什么区别。我通常不会费心声明 var 事务 - 只需返回表达式的结果。

标签: c# using


【解决方案1】:

是的,可能会有副作用。例如,如果您在 ASP.NET MVC Action 方法中使用相同的技术,您将收到以下错误:“ObjectContext 实例已被释放,不能再用于需要连接的操作”

public ActionResult GetMostRecentTransaction(int singleId)
{
    using (var db = new DataClasses1DataContext())
    {
        var transaction = (from t in db.Transactions
                              orderby t.WhenCreated descending
                              where t.Id == singleId
                              select t).SingleOrDefault();
        return PartialView("_transactionPartial", transaction);
    }
}

【讨论】:

  • 如果你在 using 语句之外定义事务,你会得到同样的错误。在这种情况下使用关键字是不相关的。
【解决方案2】:

我想,都是一样的。代码中没有什么不好的。 .NET 框架不会关心对象是在哪里创建的。重要的是它是否被引用。

【讨论】:

    【解决方案3】:

    using() 语句内部返回没有副作用。

    它是否使代码最易读是另一个讨论。

    【讨论】:

      【解决方案4】:

      看看这个

      Understanding the 'using' statement in C#

      CLR 将您的代码转换为 MSIL。 并且 using 语句得到 翻译成尝试和最后 堵塞。这是 using 语句的方式 用 IL 表示。一个使用 语句被翻译成三个 部分:获取、使用和 处理。资源第一 获得,然后附上用法 在带有 finally 的 try 语句中 条款。然后该对象被处置 在 finally 子句中。

      【讨论】:

      【解决方案5】:

      不,我认为这样更清楚。不用担心,Dispose 仍将被称为“正在退出” - 并且只有 返回值被完全评估。如果在任何时候抛出异常(包括评估返回值)Dispose 仍然会被调用。

      虽然您当然可以走更长的路,但这是两条额外的线路,只会添加杂乱无章和额外的上下文来(在心理上)跟踪。事实上,你并不真的需要额外的局部变量——尽管它在调试方面很方便。你可以只有:

      public static Transaction GetMostRecentTransaction(int singleId)
      {
          using (var db = new DataClasses1DataContext())
          {
              return (from t in db.Transactions
                      orderby t.WhenCreated descending
                      where t.Id == singleId
                      select t).SingleOrDefault();
          }
      }
      

      确实,我什至可能会想使用点表示法,并将Where 条件放在SingleOrDefault 中:

      public static Transaction GetMostRecentTransaction(int singleId)
      {
          using (var db = new DataClasses1DataContext())
          {
              return db.Transactions.OrderByDescending(t => t.WhenCreated)
                                    .SingleOrDefault(t => t.Id == singleId);
          }
      }
      

      【讨论】:

      • 当然是你@jon,如果在 using 块内抛出异常仍然安全吗?
      • 是的。 using 只是 try/finally 构造的语法糖
      • @David:正如 Mitch 所说,这很好 - 我已经更新了答案以使其更清晰 :)
      • 为什么将 OrderByDescending 与 SingleOrDefault 结合使用?
      • @erikkallen:不幸的是,LINQ 没有“MaxBy” - 因此您无法获得具有最大值的行。对于 LINQ to Objects,您可以相当轻松地编写自己的对象,但我不确定在这种情况下是否有更好的方法。你会建议什么?
      猜你喜欢
      • 1970-01-01
      • 2013-12-01
      • 1970-01-01
      • 2010-10-25
      • 1970-01-01
      • 2016-04-20
      • 1970-01-01
      • 1970-01-01
      • 2014-02-27
      相关资源
      最近更新 更多