使用 With...End With 语句与 Using 语句在 VB.NET 中的区别

12 浏览
0 Comments

使用 With...End With 语句与 Using 语句在 VB.NET 中的区别

我刚刚发现像C#一样,VB.NET也有Using关键字。

到目前为止,我以为它没有(我知道这很愚蠢...),所以做了这样的事情:

With New OleDbConnection(MyConnectionString)
   ' 做一些事情
End With

与使用Using语句相比,这样做有什么影响呢?

Using cn as New OleDBConnection(MyConnectionString)

With cn

' 用cn做一些事情

End With

End Using

更新:

我应该补充说明,我知道Using语句在退出构造时会销毁对象。

然而,据我所知,With New ...结构将在其超出范围时将对象标记为准备进行垃圾回收。

所以我的问题实际上是,唯一的区别是使用Using时我会立即释放内存,而使用With结构时,它将在垃圾回收时释放内存?或者我漏掉了更重要的东西?

这是否有任何最佳实践的影响?我是否应该去重写所有使用With New MyDisposableObject() ... End With的代码,改为Using o as New MyDisposableObject()

0
0 Comments

使用中文输出:

使用With语句/块和使用Using语句/块在VB.NET中的问题和解决方法

With语句/块:

With语句/块的作用是允许我们在一个深度嵌套的对象上按顺序设置多个属性。假设我们有一个对象,并且我们想要在它上面设置一系列属性,我们可以通过一连串的点来访问该对象。然而,每次设置属性时都要通过这一系列的点来访问相同的对象可能会变得效率低下。With语句/块可以避免这个问题,它只需要通过一次访问该对象,并将其存储在临时变量中,然后可以直接在临时变量上设置属性。

下面是一个例子,展示了使用With语句/块的效果:

With MyClass.MemberClass.AnotherMemberClass.Items(0)
    .Color   = Blue
    .Width   = 10
    .Height  = 5
    .Shape   = Circle
    .Texture = Shiny
    .Volume  = Loud
End With

这段代码的效果与下面的代码相同:

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

使用With语句/块可以提高代码的可读性,但在性能方面的优势并不明显。

With New语句/块:

With New语句/块与With语句/块的作用相同,都是为了在一个对象上设置多个属性。不同之处在于,With New语句/块会在内部创建一个临时变量来存储对象,而不需要显式声明一个变量。然而,使用With New语句/块的优势并不明显,因为如果需要创建一个对象,最好还是显式声明一个变量来持有它。

使用代码中的With New语句/块的情况非常少见,因为它并没有带来明显的好处。

Using语句/块:

Using语句/块在VB.NET中非常有用,应该经常在代码中使用。它仅适用于实现了IDisposable接口模式的类型,即具有Dispose方法的类型。在使用实现了IDisposable接口的对象时,我们应该始终调用Dispose方法来释放其占用的非托管资源。

使用Using语句/块可以确保在代码块结束时调用Dispose方法,即使在代码块内部发生异常也是如此。下面是一个使用Using语句/块的例子:

Using g As Graphics = myForm.CreateGraphics()
    g.DrawLine(Pens.Blue, 10, 10, 100, 100)
    ' ...其他操作
End Using

Using语句/块可以用于创建对象和已经创建的对象,它确保Dispose方法得到调用,以正确释放对象的非托管资源。

With语句/块用于在一个深度嵌套的对象上按顺序设置多个属性,提高了代码的可读性。With New语句/块与With语句/块的功能相同,但使用With New语句/块的优势并不明显。Using语句/块用于确保在代码块结束时调用Dispose方法,释放对象的非托管资源。在处理实现了IDisposable接口的对象时,应该始终使用Using语句/块来确保资源的正确释放。

0
0 Comments

在VB.NET中,使用With...End WithUsing语句来处理对象的释放和作用域结束时的清理。这两种方法都可以用来简化代码并提高可读性,但在某些情况下会出现一些问题。

问题的根源在于在With...End With语句中,对象的Dispose()方法没有被显式地调用。在Using语句中,对象的Dispose()方法会在作用域结束时自动调用。

解决这个问题的方法是使用Using语句来代替With...End With语句。这样可以确保对象在作用域结束时被正确地释放。下面是一个示例:

Using cn as New OleDBConnection(MyConnectionString)
    With cn
        ' Do stuff with cn
    End With
End using

在这个示例中,cn.Dispose()会在Using语句结束时自动调用。

另一个问题是,在使用命名对象时,可以创建监视器和在即时窗口中使用?cn来查看对象的值。但是在使用无名称的对象时,这些操作是不可用的。

总结起来,为了确保对象在作用域结束时被正确释放,并且使代码更加可读和简洁,我们应该使用Using语句来代替With...End With语句。这样可以避免因为忘记显式调用Dispose()方法而导致的资源泄漏问题。

0
0 Comments

在VB.NET中,使用With...End With可以在指定的对象上执行一系列语句,而无需多次指定对象的名称。

Using块的行为类似于Try...Finally结构,在该结构中,Try块使用资源,而Finally块对其进行释放。

托管资源由垃圾回收器自动处理,无需额外的编码。

您不需要使用Using或With语句。

有时,您的代码需要非托管资源。您需要负责它们的处理。Using块保证在代码完成后调用对象的Dispose方法。

这是否意味着Using将调用非托管资源的Dispose()方法?我以为所有属于.NET框架的对象都是托管的?

非托管资源包括文件句柄、COM包装器和数据库连接。声明实现所有资源清理逻辑的Dispose方法,编译器将在Using块中调用它。

谢谢。所以,如果我理解正确的话,没有显式调用Dispose()的数据库连接将永远不会被垃圾回收?

_ominae:托管资源是一个对象,已经要求外部实体在其代表之前执行某些操作,已经要求垃圾回收器在其被放弃时通知其,并且如果给予此类通知,将向其他实体通知其服务不再需要。非托管资源是与外部实体的协议,以便代表一个对象执行某些操作,直至另行通知,同时对象承诺提供此类通知,但没有任何方式确保如果对象被放弃通知将被传送。

谢谢,这是一个非常好的解释!

_ominae:谢谢。我认为“非托管资源”经常被定义为文件、GDI句柄和其他类似的东西是不幸的。尽管GDI句柄是一种非托管资源,但这是因为从GDI获取一个句柄的代码也承诺将其释放。请注意,非托管资源可以完全存在于托管代码中。事件订阅和锁定是最常见的例子;可回收的对象池是另一个例子。假设,例如,代码将需要创建和放弃大量的1024元素的double数组。

_ominae:重复创建和放弃1024元素的double[]数组可能很昂贵。如果代码实际上不需要double[],而是可以通过实现double this[int]的包装器来满足需求,那么包装器工厂可以具有一个double[][],并且包装器结构可以包括两个UInt16值,用于指示它拥有的工厂数组的槽,以及一个分配序列计数。只要代码在每个“数组”完成后调用Dispose方法,这种方法有时可以显著提高GC性能。

0