yu_*_*nae 10 vb.net scope idisposable using-statement with-statement
我刚刚发现像C#一样,VB.NET也有using关键字.
到现在为止,我认为它没有它(愚蠢的我,我知道......)并做了这样的事情:
With New OleDbConnection(MyConnectionString)
' Do stuff
End With
Run Code Online (Sandbox Code Playgroud)
与使用这样的using语句相比,这有什么影响
Using cn as New OleDBConnection(MyConnectionString)
With cn
' Do stuff with cn
End With
End using
Run Code Online (Sandbox Code Playgroud)
更新:
我应该补充一点,我熟悉using语句的作用,因为它在退出构造时处理了对象.
但是,据我所知,With New ...构造将使对象在对象超出范围时将其标记为垃圾收集.
所以我的问题是,唯一的区别在于using我将立即释放内存,而对于With构造,只要GC感觉它就会被释放吗?或者我错过了更大的东西?
是否有最佳实践意义?我应该去重写所有的代码我用With New MyDisposableObject() ... End With的Using o as New MyDisposableObject()?
Cod*_*ray 15
With 声明/块但是,据我所知,With New ...构造将使对象在对象超出范围时将其标记为垃圾收集.
这既是真实的,也不是真的.从某种意义上说,所有对象都被"标记"(纯粹主义者可能会用这个术语狡辩,但细节不相关),因为它们在超出范围时已准备好进行垃圾收集.但从那时起,它也不完全正确,因为With关于这种行为的关键字并没有什么特别之处.当对象超出范围时,它有资格进行垃圾回收.期.这对方法级范围真和它的块级范围真(例如,With,For,Using,等等).
但这不是你使用的原因With.原因是它允许您在深层嵌套对象上按顺序设置多个属性.换句话说,假设您有一个对象要在其上设置一组属性,并以这种方式访问它:MyClass.MemberClass.AnotherMemberClass.Items(0).看到所有这些点?它(在理论上)编写代码时效率低下,这些代码必须反复遍历这一系列的点,以便每次在其上设置属性时访问完全相同的对象.如果您对C或C++(或任何其他具有指针的语言)有所了解,您可以将每个点视为暗示指针取消引用.该With语句基本上只遍历所有间接,将结果对象存储在临时变量中,并允许您直接在存储在临时变量中的对象上设置属性.
也许一些代码可以帮助使事情更清晰.每当你看到一个点,想想可能会很慢!
假设您从以下代码开始,从深层嵌套的Items集合中检索对象1 并在其上设置多个属性.看看我们有多少次检索对象,即使它每次都是完全相同的对象?
MyClass.MemberClass.AnotherMemberClass.Items(0).Color = Blue
MyClass.MemberClass.AnotherMemberClass.Items(0).Width = 10
MyClass.MemberClass.AnotherMemberClass.Items(0).Height = 5
MyClass.MemberClass.AnotherMemberClass.Items(0).Shape = Circle
MyClass.MemberClass.AnotherMemberClass.Items(0).Texture = Shiny
MyClass.MemberClass.AnotherMemberClass.Items(0).Volume = Loud
Run Code Online (Sandbox Code Playgroud)
现在我们修改该代码以使用With块:
With MyClass.MemberClass.AnotherMemberClass.Items(0)
.Color = Blue
.Width = 10
.Height = 5
.Shape = Circle
.Texture = Shiny
.Volume = Loud
End With
Run Code Online (Sandbox Code Playgroud)
但是,此处的效果与以下代码相同:
Dim tempObj As MyObject = MyClass.MemberClass.AnotherMemberClass.Items(0)
tempObj.Color = Blue
tempObj.Width = 10
tempObj.Height = 5
tempObj.Shape = Circle
tempObj.Texture = Shiny
tempObj.Volume = Loud
Run Code Online (Sandbox Code Playgroud)
当然,您不会引入新的范围,因此tempObj在更高级别的范围结束之前不会超出范围(因此有资格进行垃圾收集),但这几乎不是一个相关问题.性能增益(如果有的话)附加到后两个代码片段.
如今使用块的真正胜利With不是性能,而是可读性.有关更多想法With,可能的性能改进,样式建议等,请参阅此问题的答案.
With New?将New关键字添加到With语句与我们刚才讨论的效果完全相同(创建一个本地临时变量来保存对象),除了它几乎完全没有意义.如果你需要创建一个对象New,你也可以声明一个变量来保存它.您可能稍后需要对该对象执行某些操作,例如将其传递给另一个方法,并且您不能在With块中执行此操作.
似乎唯一的目的With New是它允许你避免显式变量声明,而不是让编译器隐式地执行它.叫我疯了,但我认为没有优势.
事实上,我可以说我从未见过任何使用此语法的实际代码.我在Google上唯一能找到的就是这样的废话(Call无论如何都是一个更好的选择).
Using 声明/块不同With,Using它非常有用,应该经常出现在典型的VB.NET代码中.但是,它的适用性非常有限:它仅适用于类型实现IDisposable接口模式的对象.你可以通过检查对象是否有一个Dispose你应该在完成它时调用的方法来释放任何非托管资源.
顺便说一下,当一个对象有一个Dispose方法时,你应该总是遵循一条规则:你应该在你完成对象使用时总是调用它.如果你不这样做,它不一定是世界的尽头 - 垃圾收集器可能会保存你的培根 - 但它是记录合同的一部分,并且总是很好的做法,你需要调用Dispose提供它的每个对象.
如果您尝试包装未IDisposable在Using块中实现的对象的创建,编译器将咆哮您并生成错误.它对任何其他类型没有意义,因为它的功能基本上等同于Try/ Finallyblock:
Try
' [1: Create/acquire the object]
Dim g As Graphics = myForm.CreateGraphics()
' [2: Use the object]
g.DrawLine(Pens.Blue, 10, 10, 100, 100)
' ... etc.
End Try
Finally
' [3: Ensure that the object gets disposed, no matter what!]
g.Dispose()
End Finally
Run Code Online (Sandbox Code Playgroud)
但是当你开始嵌套时,这很难看并且变得相当笨拙(就像我们创建了一个Pen需要处理的对象一样).相反,我们使用Using,具有相同的效果:
' [1: Create/acquire the object]
Using g As Graphics = myForm.CreateGraphics()
' [2: Use the object]
g.DrawLine(Pens.Blue, 10, 10, 100, 100)
' ...etc.
End Using ' [3: Ensure that the object gets disposed, no matter what!]
Run Code Online (Sandbox Code Playgroud)
该Using语句适用于您首先获取的对象(使用New关键字或通过调用方法CreateGraphics),以及您已创建的对象.在这两种情况下,它都可以确保Dispose调用该方法,即使在块内某处抛出异常,也可以确保对象的非托管资源得到正确处理.
它让我有点害怕你在VB.NET中编写代码而不知道该Using语句.您不会将它用于创建所有对象,但在处理实现的对象时非常重要IDisposable.您肯定应该返回并重新检查您的代码,以确保您在适当的时候使用它!
通过使用With ... End With,您可以对指定对象执行一系列语句,而无需多次指定对象的名称.
Using块的行为类似于Try ... Finally构造,其中Try块使用资源而Finally块处理它们.
托管资源由垃圾收集器处理,无需您进行任何额外编码.您不需要使用Using或With语句.有时您的代码需要非托管资源.您负责处置.一个使用块保证了处置,当你的代码与他们完成的对象上调用方法.