为啥使用比使用更好?
Posted
技术标签:
【中文标题】为啥使用比使用更好?【英文标题】:Why is use better than using?为什么使用比使用更好? 【发布时间】:2011-06-30 02:45:00 【问题描述】:根据this MSDN page 的最后一句话,use
优先于using
。我在别处听说过(例如this answer)。为什么是这样?我意识到use
是后来添加的。但是有什么区别呢?从表面上看,using
似乎更有用,因为您可以控制何时调用Dispose()
,并且如果需要,您可以显式忽略绑定值(例如,(fun _ -> ...)
)。
【问题讨论】:
【参考方案1】:您也可以控制何时使用use
调用 dispose,只需使用通常的作用域构造(如括号或begin
-end
),例如
let F() =
let x = 4
(
use file = System.IO.File.Open("foo.xml", System.IO.FileMode.Append)
let z = 4
printfn "file still open here"
)
printfn "file was already closed/disposed"
但我认为这很少有用。我认为不想命名/使用IDisposable
对象也很少见。 use
在语法上更方便,95% 的时间都在做你需要的事情,所以我认为这就是为什么它是首选的原因。
【讨论】:
语法上的怪异似乎是支持using
的另一个原因。你知道他们是否会产生不同的 IL 吗?
我希望他们产生类似的 IL,尽管我不知道也不关心。至于语法上的怪异,再一次,没有人写这样的代码,因为没有人关心Dispose
是在函数结束前两行调用还是在函数结束时调用。重要的场景极为罕见。只需使用use
。
在use
作用域结束后 需要您写一些东西的一种情况是,如果您需要正确测试已释放的对象(锁定的文件再次可写) ),或者例如使用信号量。尽管如此,只需将 use
包装在一个函数中并在调用该函数后调用您的发布后代码就足够了,并且不需要像本示例中那样进行范围界定。
有趣的是,每个人似乎都缺少use ... in ...
语法来控制范围。我什至不知道你可以用你展示的括号来做到这一点;我认为唯一的方法是使用in
。例如:gist.github.com/jwosty/cfbf9cc67e9d051f2194895d37298cf9【参考方案2】:
我认为更喜欢use
的原因只是语法更简单。许多其他语言结构可以表示为函数(例如try .. with
、for
、while
,...)。如果语言设计者添加了更简单的语法,为什么不使用它...
正如我在earlier answer you referenced 中所写,即使使用use
,您也可以精确控制范围。 (这样,您甚至可以在 object expressions 类声明的构造函数中使用它。)但大多数时候,自动行为就很好(这使得构造比 C# 中的 using
更简单)。
在需要明确控制范围的情况下,是否使用use
或using
是个人喜好问题。如果您不喜欢 use
的明确范围(我承认这看起来有点奇怪,但对我来说很好用),您可以使用 using
。
编辑:在类声明中,您不能例如写:
type Foo() =
use a = new Whatever()
// ...
因为a
的范围(可能)是实例的整个生命周期。 (虽然我认为这可能很有用,它可以将IDisposable
的自动实现添加到您的类型中)。如果你使用using
,就不会遇到这种麻烦。
【讨论】:
我尝试了对象表达式,但无法弄清楚您提到的限制。能详细点吗? @Daniel:对不起,我的意思是类声明——不是对象表达式! 我仍然没有找到限制。using
在构造函数中似乎可以正常工作。
对不起,我误会了。我认为该限制适用于using
。谢谢你的解释。【参考方案3】:
就我个人而言,我更喜欢use
而不是using
,原因与我喜欢的原因相同
let a = some_expr
some_stuff_with_a
到
(fun a -> some_stuff_with_a) some_expr
使用绑定表单,您通常可以避免使用一组括号,并且标识符与其所绑定的值之间的关联在空间上更接近且更易于查看。
【讨论】:
【参考方案4】:针对use
的示例优于using
:
using
优于 use
,因为using
可以写在一行,而use
不能。
例如,xx
是函数 fct 从资源中返回值的函数,该资源由 yy
使用给定参数 p
打开。
let xx p = using (yy(p)) (fun resource-> fct resource) // <-- this is OK
let xx p = (use resource = yy(p); fct resource) // <-- this is Not OK
【讨论】:
您需要使用in
,如:let xx p = (use resource = yy(p) in fct resource)
。以上是关于为啥使用比使用更好?的主要内容,如果未能解决你的问题,请参考以下文章
为啥门控激活函数(在 Wavenet 中使用)比 ReLU 工作得更好?