静态关键字的正确使用?

8
关于static关键字。
到目前为止,通过自己的研究,我对static关键字有一个大致的了解,但是我觉得所有这些不同的描述和细节只会让我更加困惑。目前,我真的不知道如何正确地使用"static";它似乎在C#和VB.NET之间使用不同,并且在语言内部根据你所使用的用途而有所不同...
在阅读MSDN文章Static (Visual Basic) 时,许多问题浮现,特别是当我读到这句话时:
通常情况下,过程中的局部变量在过程终止时就会停止存在。而static变量仍然存在并保留其最近的值。
  1. VB.NET版本的 static 是否与C#或Java相同,大多数语言的概念是否相同?

  2. 如果 static 在类中保持一个值,并且我们能够在不实例化该类的情况下访问该特定成员、函数,则可以放心使用吗?换句话说,在使用类内的 static 时,我们应该保持警惕吗?它们让我联想到全局变量。也许我只是无知,需要更多练习才能理解它们的用途。

  3. 在哪些场景下使用 static 有益于促进代码的重复利用性?

3个回答

9
在C#中,static关键字的含义与VB.NET中的shared关键字相同。具体而言,来自于Static Classes and Static Class Members (C# Programming Guide)

静态类和类成员被用来创建无需创建类实例即可访问的数据和函数。

在VB.NET中,static的工作方式有很大不同,因为它适用于变量,而非类型。

我不知道这种行为在C#中是否有等价的语法。

1) VB.NET版本的static与C#或Java相同吗?对于大多数编程语言,概念是否相同?

不同。但是,shared是相同的。

2) 如果静态变量在一个类中保留数值,并且我们能够访问该特定成员、函数而不实例化该类——这种使用方式安全吗?换句话说,当在类中使用静态变量时,我们是否应该保持警惕?它们让我想起全局变量,也许我只是理解不够深入。

一定要非常小心,它们对应用程序域是全局的。

3) 什么情况下使用静态有益于代码重用和推广?

我使用静态列表缓存一组数据,这些数据用于填充下拉列表,这样我就不必反复访问SQL Server等等。


感谢aswayer提供如此快速和详细的答案,这确实有助于理解这个概念。 - Dayan

6

其他答案已经讲解了C#中static的用法,那我来说一下在VB.NET中的Static,因为你提到了MSDN关于它的文章。当你在VB.NET中定义一个Static局部变量时,编译器会将其转换为一个类级别的变量,只能由声明该变量的函数内的代码引用。该变量是实例变量还是共享变量取决于包含该函数的函数。例如,以下代码:

Public Class StaticTest

    Public Function Process(value As Integer) As Integer
        Static lastValue As Integer
        Dim result As Integer
        If value > 0 Then
            result = value
            lastValue = value
        Else
            result = lastValue
        End If
        Return result
    End Function

End Class

反编译后的结果如下:

Public Class StaticTest
    ' Methods
    <DebuggerNonUserCode> _
    Public Sub New()
    End Sub

    Public Function Process(ByVal value As Integer) As Integer
        If (value > 0) Then
            Dim result As Integer = value
            Me.$STATIC$Process$20188$lastValue = value
            Return result
        End If
       Return Me.$STATIC$Process$20188$lastValue
    End Function

    ' Fields
    Private $STATIC$Process$20188$lastValue As Integer
End Class

我注意到如果在函数进入时将lastValue设置为value,编译器还会创建某种初始化代码和额外字段,因此有些情况下Static本地变量确实会生成一些额外的代码。
我建议避免使用Static本地变量,因为与另一种选择——实际声明类级实例变量相比,我认为它们更加令人困惑而不是有用。静态变量的权衡如下:
正面:
  • 不能在另一个函数中访问
反面:
  • 不能在构造函数中初始化(但可以在声明时内联初始化,这会产生我上面提到的额外的init字段/代码)
  • 不能按照您通常放置类本地变量的方式进行定位
  • 看起来像本地变量,但实际上不是

5
  1. VB.NET中的shared与C#中的static是相同的。而C#的static与Java和大多数其他语言中的静态基本相同,概念是通用的。
  2. 这是一个有点肯定又有点否定的问题。在不知道自己在做什么的情况下,你不应该随意地使用static。但是,在许多情况下它们都非常有用(关于这一点请看第三个问题)。它们并不像全局变量,因为它们仍然通过所属类进行“名称空间”和组织。
  3. 静态成员通常用于实用方法和类。例如,C#将大部分Math库实现为静态方法,因为它们只是做计算,并没有任何其他副作用。总的来说,如果你的方法没有副作用,并且所有需要执行其工作的数据都以参数的形式提供。如果您希望在类的实例之间共享某些数据,也可以使用静态属性(例如,跟踪给定方法被调用的次数或类似信息)。静态还具有一些内存使用优势,因为它允许您只创建一个类或方法实例,然后在整个应用程序中共享,而不是为每个使用创建新的副本。您还可以使用静态类来扩展方法,但这是另一个讨论。
  4. 虽然您没有专门提问,但值得一提的是缺点。避免静态最大的原因是可维护性。您无法轻松地继承或扩展静态类,这是需要考虑的主要问题。只要坚持组合优于继承的规则,这未必是一个断言问题,但是对于静态类的继承和多态性的缺乏是一个主要的缺点。由于这一个问题,很多人建议在所有情况下都避免使用静态。

非常详细的解释!非常感谢Tim,这真的解决了很多问题。 :) - Dayan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接