Reputation: 1422
I read some articles and blogs on Implementation if IDisposable and GC working set. However, I could not understand the core areas of differentiation like: Following is code of my test class:
Imports System.ComponentModel
Namespace Classes
Public Class BaseClass
Implements INotifyPropertyChanged
Implements IDisposable
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Protected Friend Sub NotifyPropertyChanged(ByVal info As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects).
End If
End If
Me.disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
Public Class GenreClass
Inherits BaseClass
#Region "Private Variables"
Private _GenreValue As String
Private _IconValue As String
Private _IsSelectedValue As Boolean
Private _IsExpandedValue As Boolean
#End Region
#Region "Property Variables"
Property Genre As String
Get
Return _GenreValue
End Get
Set(Value As String)
If Not _GenreValue = Value Then
_GenreValue = Value
NotifyPropertyChanged("Genre")
End If
End Set
End Property
Property Icon As String
Get
Return _IconValue
End Get
Set(Value As String)
If Not _IconValue = Value Then
_IconValue = Value
NotifyPropertyChanged("Icon")
End If
End Set
End Property
Property IsSelected As Boolean
Get
Return _IsSelectedValue
End Get
Set(Value As Boolean)
If Not _IsSelectedValue = Value Then
_IsSelectedValue = Value
NotifyPropertyChanged("IsSelected")
End If
End Set
End Property
Property IsExpanded As Boolean
Get
Return _IsExpandedValue
End Get
Set(Value As Boolean)
If Not _IsExpandedValue = Value Then
_IsExpandedValue = Value
NotifyPropertyChanged("IsExpanded")
End If
End Set
End Property
#End Region
Protected Overrides Sub Dispose(disposing As Boolean)
Genre = Nothing
MyBase.Dispose(disposing)
End Sub
Public Overrides Function ToString() As String
Return Genre
End Function
End Class
End Namespace
My Test scenarios are as follows: Test1:
Dim list1 As New List(Of HODLib.Classes.GenreClass)
For i = 0 To 4
Using z As New HODLib.Classes.GenreClass
With z
.Genre = "asdasd"
.Icon = "asdasdasdasdasd"
.IsExpanded = True
.IsSelected = True
End With
list1.Add(z)
End Using
Next
For Each z In list1
MessageBox.Show(z.ToString)
Next
result of test1 is that GC is called immediately and I loose access to resources, I get null message.
Test2:
Dim list1 As New List(Of HODLib.Classes.GenreClass)
For i = 0 To 4
Dim z As New HODLib.Classes.GenreClass
With z
.Genre = "asdasd"
.Icon = "asdasdasdasdasd"
.IsExpanded = True
.IsSelected = True
End With
list1.Add(z)
Next
For Each z In list1
MessageBox.Show(z.ToString)
Next
Result is Dispose is never called, even for z in forloop, I dont understand this, why is z not disposed, is it waiting because the list has reference to its values?
Test3:
Dim list1 As New List(Of HODLib.Classes.GenreClass)
For i = 0 To 4
Dim z As New HODLib.Classes.GenreClass
With z
.Genre = "asdasd"
.Icon = "asdasdasdasdasd"
.IsExpanded = True
.IsSelected = True
End With
list1.Add(z)
z.Dispose()
Next
For Each z In list1
MessageBox.Show(z.ToString)
Next
Result: Test2 vs test3 is calling the dispose manually after adding to the list. Result is that I lost access to resource, I get null message. Why did this happen although I added the object to list before calling the dispose method.
Thank you.
Upvotes: 0
Views: 263
Reputation: 942267
Unfortunately, the Dispose implementation that the Visual Basic IDE auto-generates is wrong in 99.9% of all cases. You should only use it if your class has a Finalize() method or the base class has a protected Dispose(Boolean) method. Which is extremely rare, finalizers are implemented by .NET Framework classes. It is their job to wrap unmanaged resources that should be released early.
It becomes 100% wrong when you find out that you can't write any meaningful code in the Dispose() method. Like this case, your class has no fields of a type that is disposable. Setting a field to Nothing has no effect.
Upvotes: 1
Reputation: 25057
You are adding a reference to the instance z which you create. When that instance is destroyed, the reference is no longer pointing to anything. The Using
construct automatically calls Dispose for you. You can make a new copy of the object z by adding a method to the class:
Public Function Clone() As GenreClass
Return DirectCast(Me.MemberwiseClone(), GenreClass)
End Function
and use list1.Add(z.Clone)
.
See Object.MemberwiseClone Method for more information and if you need to create a deep copy.
Upvotes: 0