1

在单线程环境中考虑以下功能上的两个代码片段。假设没有其他方法,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”。我已经知道这是错误的,但主要的反对意见是关于使用Static. 我发现几个对静态变量的引用表明它们可能很危险,但它们都在谈论 Java。但是,我找不到任何好的解释来解释原因。

这两种方法有何不同?第二种方法危险吗?如果是这样,为什么?

4

3 回答 3

3

Static在 VB.Net 中与static在 Java、C#、C 或 C++ 中的不同。VB.Net 与该构造的类似物是Shared. 关于静态关键字的文档在这里:

http://msdn.microsoft.com/en-us/library/z2cty7t8.aspx

特别是,我想指出这个片段:

行为

在 Shared 过程中声明静态变量时,整个应用程序只能使用该静态变量的一份副本。您通过使用类名而不是指向类实例的变量来调用 Shared 过程。

当您在非共享过程中声明静态变量时,该类的每个实例只有一个变量副本可用。您可以使用指向类的特定实例的变量来调用非共享过程。

反对意见很可能来自于相信Static总是表现得像第一段,即使在实例方法中,当我们可以看到这里清楚地记录了情况并非如此。

相反,静态允许您声明一个变量,其生命周期是类实例的生命周期,但其访问范围仅限于单个方法。这是一种缩小变量潜在范围的方法,因此是一件好事。此外,声明为静态的变量由编译器重写以通过Monitor类保护(至少对于共享版本),为它们提供了线程安全的度量。换句话说,声明为静态的变量比类似的类范围变量更有可能完成任何需要的锁定。

但是,在这种特殊情况下,我看不到重点。除了像这样的自动实现的属性之外,您并没有真正获得任何东西:

Public ReadOnly Property GetBar2 As New Bar()
于 2013-09-24T19:54:23.523 回答
1

这可能会混淆 VB.net 的概念,Static并且Shared因为某些语言使用关键字Static来表示 VB 的用途Shared:类的所有实例共享或通用的变量/字段/属性/方法。

但这Static并不意味着在 VB 中。相反,它意味着一个例程局部变量,它在例程调用之后仍然存在(即,它的生命周期是对象范围的,而不是例程调用范围的)。

参考:http: //msdn.microsoft.com/en-us/library/z2cty7t8.aspx

所以在 VB 中,Static意味着“例程范围的可见性,对象范围的生命周期”。

Shared意味着“类范围的可见性,类/程序范围的生命周期”。

于 2013-09-24T19:55:36.340 回答
1

如果没有其他原因,我会避免使用第二种方法,因为 C 和 C# 有一个static关键字,其含义与 VB.NET 关键字的含义完全不同Static。我通常不喜欢看起来像其他语言的功能但不是的语言功能。如果有必要使用一种语言功能,尽管它与另一种语言的功能很相似,但我会使用它,但 VB.NET 的 static 关键字在这里并没有真正增加太多。实际上,它要求编译器创建变量Private字段,给它一个与任何其他字段不同的任意名称,并将方法中对变量给定名称的所有引用替换为对发明名称的引用。

从概念上讲,使用这种“本地化”字段可能被认为是可疑的,因为虽然人们可能期望一个字段只需要在一种方法中使用,但事实可能并非如此。但是,我不会太担心 vb.net 中的这个问题,因为Static如果需要,变量很容易变成普通的私有字段。如果确实需要存在同名字段,则可以Static在移动变量之前轻松地重命名该变量。

于 2013-09-24T19:58:59.180 回答