从using()语句内部返回是否有副作用?


125

从using语句内部获取DataContext 返回方法值似乎总是可以的,就像这样:

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;
    }
}

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

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


1
查看通用IL的变体可能会很有趣。我怀疑生成的IL差异不大。我通常甚至不会费心地声明var事务-只返回表达式的结果。
Jonesie

Answers:


164

不,我认为这样更清楚。不用担心,在返回值得到充分评估之后,它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);
    }
}

2
是您@jon,如果在using块中引发异常,它仍然安全吗?
戴夫·阿彻

6
是。使用只是语法糖来尝试/最终构建
Mitch Wheat

@David:就像Mitch所说的,很好-我已经更新了答案,以使内容更清楚:)
Jon Skeet 2010年

2
为什么将OrderByDescending与SingleOrDefault结合使用?
erikkallen 2010年

2
@erikkallen:不幸的是,LINQ没有“ MaxBy”-因此您无法获得具有最大值的行。对于LINQ to Objects,您可以相当轻松地编写自己的对象,但是在这种情况下,我不确定是否有更好的方法。您会建议什么呢?
乔恩·斯基特

32

看看这个

了解C#中的“使用”语句

CLR将您的代码转换为MSIL。然后using语句将转换为try,并最终阻塞。这就是IL中using语句的表示方式。using语句转换为三个部分:获取,使用和处置。首先获取资源,然后将用法包含在带有finally子句的try语句中。然后将对象放置在finally子句中。


4
一个有趣的见解。谢谢。
康坎

1
这将问题转换为:从try-final的try-block返回的任何副作用?
Henk Holterman'3


6

没有从内返回的副作用using()声明。

它是否使代码更具可读性是另一个问题。


0

我想都是一样的。代码中没有什么不好的。.NET框架不在乎对象的创建位置。重要的是是否引用它。


-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);
    }
}

2
如果您在using语句之外定义事务,则将出现相同的错误。在这种情况下,using关键字无关。
哥斯达黎加
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.