组件的初始化和终止

组件由其构造函数(在 Visual Basic 中为 Sub New)初始化,由其析构函数(在 Visual Basic 中为 Sub Finalize)销毁。当创建组件的实例时调用组件的构造函数;之后不能再调用此构造函数。在垃圾回收销毁组件并回收其内存之前调用析构函数。

Visual Basic 说明   在 Visual Basic 的早期版本中, InitializeTerminate 事件分别实现构造函数和析构函数的用途。

等待垃圾回收

当垃圾回收确定组件不能再由任何执行代码访问后,公共语言运行库将调用该组件的析构函数。如果对组件的所有引用都已释放,或者对组件的唯一引用由特定的对象保持,而该对象以同样的方式与所有执行代码隔离(例如循环引用的情况),则将发生上述情况。

鉴于用户使用完组件与调用组件的析构函数之间可能有一个延迟,在 .NET 组件的生存期中另外引入了一步:如果组件获取系统资源(如数据库连接或 Windows 系统对象的句柄),则应实现 IDisposable 接口,并提供 Dispose 方法以便组件的用户可以选择何时释放那些资源。

组件的生存期

  1. 类型初始化:当创建组件的第一个实例时,执行的第一个代码是任何共享的初始化代码。对任何共享成员的引用都将导致执行共享构造函数。这包括任何初始化的共享字段(成员变量)和可能存在的共享构造函数 (Shared Sub New)。在下列代码中,为整个类创建了引用字体。
    注意   Shared 相对应的 C# 关键字是 static,不要将其与 Visual Basic 中的 Static 关键字混淆。
        
    None.gif '  Visual Basic
    ExpandedBlockStart.gifContractedBlock.gif
    Public   Class ADrawing Class ADrawing
    InBlock.gif
    Shared ReadOnly ReferenceFont As New Font("TimesNewRoman"14)
    InBlock.gif
    ' Shared constructor does not overload other constructors.
    ExpandedSubBlockStart.gifContractedSubBlock.gif
    Shared Sub New()Sub New()
    InBlock.gif   
    ' There is no call to the base class's shared constructor.
    InBlock.gif
       ' Insert code to initialize the shared data.
    ExpandedSubBlockEnd.gif
    End Sub

    ExpandedBlockEnd.gif
    End Class

    None.gif


    注意   
    即使未创建组件的实例,类初始化仍然可以发生。例如,具有共享成员函数的 abstract (MustInherit)
    类将被初始化,而即使未创建此类的实例,那些函数仍然可由应用程序使用。
  2. 实例初始化:当创建组件的实例时,将初始化具有初始化代码的数据成员,并执行适当的构造函数重载。下列代码初始化一个私有字段并定义两个构造函数,一个在没有参数时调用,另一个在用户指定了参数时调用。
        
    None.gif '  Visual Basic
    ExpandedBlockStart.gifContractedBlock.gif
    Class AShape Class AShape
    InBlock.gif   
    Private answer As Integer = 42
    ExpandedSubBlockStart.gifContractedSubBlock.gif   
    Public Sub New()Sub New()
    InBlock.gif      
    ' Call another constructor with default initialization values.
    InBlock.gif
          MyClass.New(System.Drawing.Color.Red, 5280, DefinedSizes.Large)
    ExpandedSubBlockEnd.gif   
    End Sub

    ExpandedSubBlockStart.gifContractedSubBlock.gif   
    Public Overloads Sub New()Sub New(myColor As Color, myLength As Integer, _
    InBlock.gif            Size 
    As DefinedSizes)
    InBlock.gif      
    ' Insert code to initialize the class.
    ExpandedSubBlockEnd.gif
       End Sub

    InBlock.gif   
    ' Defines the DefinedSizes enum
    ExpandedSubBlockStart.gifContractedSubBlock.gif
       Public Enum DefinedSizesEnum DefinedSizes
    InBlock.gif      Large
    InBlock.gif      Small
    ExpandedSubBlockEnd.gif   
    End Enum

    ExpandedBlockEnd.gif
    End Class

    None.gif


    处置资源
    :如果组件实现了 IDisposable 接口,它必须提供 Dispose 方法,以便客户在用完组件后调用此方法。注意,任何从 System.ComponentModel.Component 继承的组件都已有 Dispose 的默认实现。可重写此默认实现以提供附加的清理代码。在 Dispose 方法中,组件释放它可能已分配的所有系统资源,释放对其他对象的引用,并使自身呈现为不可用。可能也存在组件适合调用它自己的 Dispose 方法的情况。下列代码处置一个具有 Dispose 方法的依赖对象。
  3.     
    None.gif '  Visual Basic
    None.gif'
     Assumes that the class implements IDisposable
    ExpandedBlockStart.gifContractedBlock.gif
    Public   Sub Dispose() Sub Dispose() Implements IDisposable.Dispose
    InBlock.gif   myWidget.Dispose
    InBlock.gif   myWidget 
    = Nothing
    InBlock.gif   
    ' Insert additional code.
    ExpandedBlockEnd.gif
    End Sub

    None.gif

    None.gif //  C#
    None.gif
    //  Assumes that the class implements IDisposable
    None.gif
    public   void  IDisposable.Dispose()
    ExpandedBlockStart.gifContractedBlock.gif
    dot.gif {
    InBlock.gif   mywidget.Dispose();
    InBlock.gif   mywidget 
    = null;
    InBlock.gif   
    // Dispose of remaining objects.
    ExpandedBlockEnd.gif
    }

    None.gif   

    调用 Dispose 后,客户应释放对组件的任何其余的引用,以便垃圾回收可以回收组件的内存。

  4. 实例析构:如果垃圾回收检测到没有对组件的其余引用,则运行库将调用组件的析构函数(Visual Basic .NET 中的 Finalize)并释放内存。您应该重写基类的 Finalize 方法(对于 Visual Basic .NET)或实现析构函数(对于 Visual C#)以实现您自己的清除代码,但应始终包括对析构函数或基类的 Finalize 方法的调用。
        
    None.gif '  Visual Basic
    ExpandedBlockStart.gifContractedBlock.gif
    Protected   Overrides   Sub Finalize() Sub Finalize()
    InBlock.gif   m_Gadget 
    = Nothing
    InBlock.gif   m_Gear 
    = Nothing
    InBlock.gif   
    MyBase.Finalize()
    ExpandedBlockEnd.gif
    End Sub

    None.gif

    None.gif //  C#
    None.gif
    //  In C#, a destructor is used instead of a Finalize method.
    None.gif
    ~ ThisClass()
    ExpandedBlockStart.gifContractedBlock.gif
    dot.gif {
    InBlock.gif   m_gadget 
    = null;
    InBlock.gif   m_gear 
    = null;
    InBlock.gif   
    // The base class finalizer is called automatically
    ExpandedBlockEnd.gif
    }

  5. 何时应实现 Dispose 方法?

如果组件从 System.ComponentModel.Component 继承,系统会提供 Dispose 的默认实现。可重写此实现以提供自定义清理代码。如果通过创建 Icomponent 的自定义实现生成组件,则应实现 IDisposable 以便为组件提供 Dispose 方法。

如果组件分配了系统对象、数据库连接或其他应在用户使用完组件后立即释放的短缺资源,则组件需要 Dispose 方法。

如果组件有对其他对象的引用,而那些对象具有 Dispose 方法,则也应实现 Dispose 方法。

为什么实现 Dispose?

根据系统活动的不同,在用户使用完组件和垃圾回收检测到组件的代码不可访问之间的时间间隔可能不可预知。如果未提供 Dispose 方法,则在这段间隔期内,组件将一直控制其资源。

最坏情况的方案

设想一下使用数据库连接却没有 Dispose 方法的服务器组件。在有大量内存的服务器上,您可能创建并释放组件的许多实例,而不会对可用内存有太大影响。在此情况下,当释放了对组件的引用后,垃圾回收可能在一段时间内不销毁组件。

最后,所有可用的数据库连接可能都被已释放但尚未销毁的组件占用了。即使服务器的内存够用,它也可能无法响应用户请求。

转载于:https://www.cnblogs.com/zman/archive/2006/07/25/458918.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值