I have a base class Base and a class Child which inherits from this base class. The base class is IDisposable.
I have a call to the Dispose method of the Child class. Is there a way to navigate to the overridden implementation in Child?
Dim oChild as Child
oChild.Dispose()
When I press F12 while having the Dispose() method selected, I end up in Base.Dispose() instead of Child.Dispose(). Note that the declaration is as the Child type.
P.S.: I do have ReSharper so if anyone would have an easy solution with ReSharper, that would work too.
Edit (code example):
Public Class CBase
Implements IDisposable
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' Disposing etc.
End If
End If
Me.disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
End Class
Public Class CChild
Inherits CBase
Protected Overrides Sub Dispose(disposing As Boolean)
Try
If disposing Then
' Dispose child specific
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
End Class
Public Class CExample
Public Sub ProvideExample()
Dim oChild As New CChild
oChild.Dispose() ' F12 on this leads me to CBase.Dispose
End Sub
End Class
Is there any Code in der overridden method?
Because normally if you press F12 you are not getting up to the base. I think it's only if there is nothing else in the overridden method?
Related
I'm trying to avoid that sub-classes of my class can override my method.
If I try to do so by using the NotOverridable keyword:
Public Class Class1
Protected NotOverridable Sub DoSomething()
End Sub
End Class
I get this error:
'NotOverridable' cannot be specified on methods that do not override another method
Let's say that you have this class:
Public Class GrandParent
Protected Sub Method1()
End Sub
Protected Overridable Sub Method2()
End Sub
End Class
and then you have this class:
Public Class Parent
Inherits GrandParent
Protected Sub Method1()
End Sub
Protected Overrides Sub Method2()
End Sub
End Class
Parent.Method2 is overriding GrandParent.Method2, just as indicated. On the other hand, Parent.Method1 is NOT overriding GrandParent.Method1. That code generates the following warning:
sub 'Method1' shadows an overloadable member declared in the base
class 'GrandParent'. If you want to overload the base method, this
method must be declared 'Overloads'.
If you change the code to the following:
Public Class Parent
Inherits GrandParent
Protected Overrides Sub Method1()
End Sub
Protected Overrides Sub Method2()
End Sub
End Class
then you get the following error:
'Protected Overrides Sub Method1()' cannot override 'Protected Sub
Method1()' because it is not declared 'Overridable'.
Shadowing is different to overloading in that shadowing honours the type of the reference while overriding honours the type of the object. That means that, if you you have a Parent object assigned to a GrandParent variable, calling Method1 will invoke GrandParent.Method1 based on the type of the reference and calling Method2 will invoke Parent.Method2 based on the type of the object. Overriding implements polymorphism where shadowing does not. The first implementation of Parent is equivalent to this:
Public Class Parent
Inherits GrandParent
Protected Shadows Sub Method1()
End Sub
Protected Overrides Sub Method2()
End Sub
End Class
If you were to then add this class:
Public Class Child
Inherits Parent
Protected Overrides Sub Method2()
End Sub
End Class
it would work as expected. If you changed the Parent class to this:
Public Class Parent
Inherits GrandParent
Protected Shadows Sub Method1()
End Sub
Protected NotOverridable Overrides Sub Method2()
End Sub
End Class
then that `Child implementation would generate this error:
'Protected Overrides Sub Method2()' cannot override 'Protected
NotOverridable Overrides Sub Method2()' because it is declared
'NotOverridable'.
That is the only reason to use the NotOverridable keyword, i.e. to prevent derived classes overriding your own overridden implementation of an inherited member.
Problem:
I have a class where I have a eventlog that logs for that particular instance of the class and logs to a shared eventlog and to track changes across all instances.
My issue is that I want the logs to be re sizable in their number of entries and I need to make sure that the shared log is never smaller than any of the instanced logs. Is it possible to check this?
What I've tried:
I've seen a-lot about GetType and reflections and I've been able to get instance names but I can't figure out how to reference data within those instances.
Below is a psuedocode of where I am at.
Public Class Test
Public InstancedLog As DataSet
Public Shared SharedLog As DataSet
Public Shared Sub ResizeSharedLog(ByRef DesiredSize As Integer)
If DesiredSize < ("check and sum up the size of all instances of InstancedLog") Then
'can't resize, too small.
Else
'resize to DesiredSize.
End If
End Sub
End Class
Any help would be much appreciated.
Here's an example of a class that tracks its own instances:
Public Class Class1
Implements IDisposable
Private Shared instances As New List(Of Class1)
Public Sub New()
instances.Add(Me)
End Sub
Public Shared Sub TouchEveryInstance()
For Each instance As Class1 In instances
'Use instance here.
Next
End Sub
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects).
instances.Remove(Me)
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose(disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
Dispose(True)
' TODO: uncomment the following line if Finalize() is overridden above.
' GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
Most of that code is auto-generated by VS when you add the Implements IDisposable line. The entire region was added automatically except the line that refers to the instances field. I added the instances field, the constructor and the TouchEveryInstance method.
In VS 2015, when I click 'Find All References' on a class definition for a class that implements IDisposable, it returns MyBase.Finalize() for every class which implements IDisposable.
NOTE: This happens when I click 'Find All References' on the class definition itself (i.e. Public Class Test123). If I click 'Find All References' on the implementation (i.e. New Test123) then it only fetches instances which use that specific New constructor. This is also confusing. In VS 2010, the class definition itself and all implementations were grouped together in one list, but in 2015 they are NOT.
Refer to the screenshot below. Even when I mousehover over class Test123, it highlights the MyBase.Finalize() method for both Test123 and Test456
Visual Studio 2010 does NOT do this. Is this a bug, or a 'new feature'?
The difficulty this causes is that for the current project at work, we manually implement IDisposable for every class. So when I click 'Find All References' on any class, it takes 10-20 seconds to find the references, and then it displays thousands of instances of MyBase.Finalize() (one for every single class), and it's basically completely useless.
Screenshot (I can't directly insert pictures with my acct yet)
Public Class Form1
Dim a As New Test123
Dim b As New Test456
End Class
Public Class Test123
Implements IDisposable
Dim A As Double = 0
'Dispose Implementation
Dim mbDisposed As Boolean = False
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Private Overloads Sub Dispose(ByVal lbDisposing As Boolean)
If Not mbDisposed Then
If lbDisposing Then
'Dispose of all nullable objects
End If
End If
mbDisposed = True
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
End Class
Public Class Test456
Implements IDisposable
Dim B As Double = 1
'Dispose Implementation
Dim mbDisposed As Boolean = False
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Private Overloads Sub Dispose(ByVal lbDisposing As Boolean)
If Not mbDisposed Then
If lbDisposing Then
'Dispose of all nullable objects
End If
End If
mbDisposed = True
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
End Class
For a given method for example, try to use "Call Hierarchy" on it to see 3 groups of calls:
Calls to its "base" implementation
Calls to its "override" implementations
Calls to its direct (current class) implementation
Helping ?
I downloaded Visual Studio 2017 RC. The "Find All References" window now contains a filtering combo box. If i select "Group by: Definition Only", then the actual references I'm trying to find appear in the first "group" in the list.
All the Finalize() methods from every other class in the project in the project are still listed, but they are placed in separate groups below. So technically this bug still exists, but I am able to easily filter out the garbage that I don't want to see as shown in this snapshot
I have a class in which I have declared a FileStream and a StreamReader:
Option Strict Off
Option Explicit On
Friend Class clsFileReader
Private _fs As IO.FileStream
Private _sr As IO.StreamReader
I would like ask if I explicitely need to close these like this:
Protected Overrides Sub Finalize()
_fs.Close()
_sr.Close()
End Sub
... or if that is done automatically.
Thank you for the help!
ps: I can not use "using" because I want to read the file line by line like this:
Public Function ReadLine() As String
Debug.Assert(Not _sr.EndOfStream)
_sCurrentLineString = _sr.ReadLine
_iCurentLineIndex = _iCurentLineIndex + 1
Return _sCurrentLineString
End Function
I would suggest you use the same fonctionality as found in the stream. Implement the IDisposable interface and call .Dispose on your class instance when you're done with it. Same as you would do with a stream.
Here's a quick example.
Class clsFileReader : Implements IDisposable
Private _fs As IO.FileStream
Private _sr As IO.StreamReader
' Flag: Has Dispose already been called?
Dim disposed As Boolean = False
' Public implementation of Dispose pattern callable by consumers.
Public Sub Dispose() _
Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
' Protected implementation of Dispose pattern.
Protected Overridable Sub Dispose(disposing As Boolean)
If disposed Then Return
If disposing Then
' Free any other managed objects here.
'
_fs.Close()
_sr.Close()
End If
' Free any unmanaged objects here.
'
disposed = True
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
End Sub
End Class
I've been trying to write this very simple code myself but I find it a bit difficult (Reflection.Emit is very new to me), so here I am.
What I need is an entire class that inherits from a super class and override a method - all written to be emitted and created in runtime.
My super class, ClassA, is an empty class without any code except for the Implement IDispose:
Namespace Basic
Public Class ClassA
Implements IDisposable
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects).
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
End Namespace
My ClassB is the one to be created at runtime. It should look like this:
Namespace Basic
Public Class ClassB
Inherits ClassA
Protected Overrides Sub Dispose(disposing As Boolean)
MyBase.Dispose(disposing)
End Sub
End Class
End Namespace
I've been searching alot and I cannot find out how to write the inherit code, when creating ClassB on fly.
Also, I'm not that sure about writing the call-segment in the OPCode for ClassB
.method family strict virtual instance void
Dispose(bool disposing) cil managed
{
// Code size 11 (0xb)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: call instance void WindowsApplication1.Basic.ClassA::Dispose(bool)
IL_0008: nop
IL_0009: nop
IL_000a: ret
} // end of method ClassB::Dispose
Anyone?
This is what I neded up with.
This class holds the iDisposable:
Public Class Super
Implements IDisposable
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
For Each prop As PropertyInfo In Me.GetType.GetProperties
If prop.CanWrite Then
prop.SetValue(Me, Nothing, Nothing)
End If
Next
' TODO: dispose managed state (managed objects).
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Overridable Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
...and this is my class builder that inherits from Super
Public Class ClassCreator
Public Shared Function CreateClass() As Object
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US")
Thread.CurrentThread.CurrentUICulture = New CultureInfo("en-US")
Dim name As String = "DefineMethodOverrideExample"
Dim myAssemblyName As New AssemblyName(name)
Dim myAssemblyBuilder As AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(myAssemblyName, AssemblyBuilderAccess.RunAndSave)
Dim myModuleBuilder As ModuleBuilder = myAssemblyBuilder.DefineDynamicModule(name, name & ".dll")
Dim myTypebuilder As TypeBuilder = myModuleBuilder.DefineType("C", TypeAttributes.Public, GetType(Super))
Dim myMethodBuilder As MethodBuilder = myTypebuilder.DefineMethod("Dispose",
MethodAttributes.Public Or MethodAttributes.ReuseSlot Or MethodAttributes.Virtual Or MethodAttributes.HideBySig,
Nothing,
Type.EmptyTypes)
Dim il As ILGenerator = myMethodBuilder.GetILGenerator()
il = myMethodBuilder.GetILGenerator()
il.Emit(OpCodes.Nop)
il.Emit(OpCodes.Ldarg_0)
il.Emit(OpCodes.Call, GetType(Super).GetMethod("Dispose"))
il.Emit(OpCodes.Nop)
il.Emit(OpCodes.Nop)
il.Emit(OpCodes.Ret)
Dim tc As Type = myTypebuilder.CreateType()
myAssemblyBuilder.Save(name & ".dll")
Dim test As Object = Activator.CreateInstance(tc)
Return test
End Function
End Class
The class builder build classes that can be Disposed, which was what I wanted :)