在单线程环境中考虑以下功能性的两个代码片段。假设Foo
中没有其他方法,我相信这些方法在功能上是相同的。
Class Foo
Private _Bar As Bar
Public ReadOnly Property GetBar As Bar
Get
If IsNothing(_Bar) Then
_Bar = New Bar
End If
Return _Bar
End Get
End Property
End Class
并且
Class Foo
Public ReadOnly Property GetBar2 As Bar
Get
Static _Bar As New Bar
Return _Bar
End Get
End Property
End Class
今天我在第二种方法之后遇到了代码挑战,因为“每次都会调用New”。我已经知道that is false,但主要的反对意见是关于Static
的使用。我发现了几个对静态变量的引用,表明它们可能很危险,但它们都在谈论Java。但是,我无法找到任何关于原因的好解释。
这两种方法有何不同?第二种方法危险吗?如果是这样,为什么?
答案 0 :(得分:3)
Static
与Java,C#,C或C ++中的static
不同。 VB.Net与该构造的类比是Shared
。有关Static关键字的文档如下:
特别是,我想指出这个片段:
<强>行为强>
在Shared过程中声明静态变量时,只有一个静态变量副本可用于整个应用程序。您可以使用类名调用Shared过程,而不是指向类实例的变量。
在非共享的过程中声明静态变量时,该类的每个实例只能使用该变量的一个副本。您可以使用指向该类的特定实例的变量来调用非共享过程。
反对意见可能来自于相信Static
总是表现得像第一段,即使在实例方法中,当我们在这里看到明确证明情况并非如此时。
相反,Static允许您声明一个变量,其 lifetime-scope 是类实例的变量,但其访问范围仅限于单个方法。这是缩小变量的潜在范围的一种方式,因此是一件好事。此外,声明为Static的变量由编译器重写,以通过Monitor
类(至少对于Shared版本)进行保护,从而为它们提供线程安全性的测量。换句话说,声明为Static的变量更可能以完成与类似的类范围变量相关的任何所需锁定。
但在这种特殊情况下,我没有看到这一点。除了像这样的自动实现的属性之外,你真的没有获得任何东西:
Public ReadOnly Property GetBar2 As New Bar()
答案 1 :(得分:1)
这可能会混淆Static
和Shared
的VB.net概念,因为有些语言使用关键字Static
来表示VB使用Shared
的内容:变量/对所有类实例共享或共用的字段/属性/方法。
但是Static
并不意味着在VB中。相反,它意味着一个例程本地变量,它持续超出了例程的调用(即,它的生命周期是对象作用域而不是例程调用作用域)。
参考:http://msdn.microsoft.com/en-us/library/z2cty7t8.aspx
所以在VB中,Static
表示“例程范围的可见性,对象范围的生命周期”。
而Shared
的意思是“类范围的可见性,类/程序范围的生命周期”。
答案 2 :(得分:1)
如果没有其他原因,除了C和C#的static
关键字的含义与VB.NET Static
关键字的含义完全不同之外,我会避免使用第二种方法。我一般不喜欢看起来像其他语言的功能但不是。如果有必要使用语言功能,尽管它与其他语言的功能非常相似,我将使用它,但VB.NET静态关键字在这里并没有真正增加太多。实际上,它要求编译器生成变量Private
字段,给它一个不同于任何其他字段的任意名称,并替换方法中对变量的给定名称的所有引用引用了本发明的名称。
从概念上讲,使用这样的“本地化”字段可能被认为是可疑的,因为虽然人们可能期望只需要在一种方法中使用字段,但这可能结果不是真的。但是,我不会过多担心vb.net中的这个问题,因为如果需要,Static
变量很容易变成普通的私有字段。如果在需要的时候出现了一个具有相同名称的字段,可以在移动之前轻松重命名Static
变量。