I know there are quite a few questions and other webpages explaining the difference between shadowing and overriding. Unfortunately I still haven't understood which one I should use.
My situation is this: I wish to make a class that inherits the System.ComponentModel.BindingList
of a specific type, to make operations like add and remove threadsafe.
If my basic class is as follows:
Imports System.ComponentModel
Public Class DeviceUnderTestBindingList
Inherits System.ComponentModel.BindingList(Of DeviceUnderTest)
Private Sub New()
MyBase.New()
End Sub
Public Sub Add(ByVal device As DeviceUnderTest)
MyBase.Add(device)
End Sub
Public Sub Remove(ByVal deviceKey As UInteger)
MyBase.Remove(deviceKey)
End Sub
End Class
I would like someone using this class to only be able to use the .Add and .Remove methods that I have provided, and not the ones from BindingList. But I would like my class to be able to access the BindingList methods internally, e.g. you can see that my .Add method currently calls the BindingList.Add method at some point.
I have tried it with both shadows
and overrides
and they both seem to give the same effect, so is one more correct than the other in this situation and why?
Overloading is an entirely different concept. In essence, overloading allows you to have multiple Add()
and Remove()
methods while overriding a method 'replaces' the original behavior. Shadowing is somewhere in between. Shadowing 'hides' the original behavior, but you can still access the base method by casting to the base type.
Generally speaking, you don't shadow a member if you can instead override it. Unless you have a very specific reason to do so.
Note that you can't both override and shadow the same member. But you can, for example, both override and overload the original Add()
method.
EDIT
You can't override the Add()
method, but you can override OnAddingNew()
. Similarly, you can't override Remove()
, but you can override RemoveItem()
. I don't know the specifics for this class, but I suspect that Remove()
uses RemoveItem()
under the covers.
Your implementation could look somewhat like this:
Imports System.ComponentModel
Imports System.Collections.ObjectModel
Public Class DeviceUnderTestBindingList
Inherits BindingList(Of DeviceUnderTest)
Private Sub New()
MyBase.New()
End Sub
#Region "Add()"
Protected Overrides Sub OnAddingNew(e As AddingNewEventArgs)
Dim newDevice As DeviceUnderTest = DirectCast(e.NewObject, DeviceUnderTest)
Try
If (Not IsValidEntry(newDevice)) Then ' don't add the device to the list
Exit Sub
End If
' (optionally) run additional code
DoSomethingWith(newDevice)
Finally
MyBase.OnAddingNew(e)
End Try
End Sub
Private Function IsValidEntry(device As DeviceUnderTest) As Boolean
' determine whether the specified device should be added to the list
Return True Or False
End Function
Private Sub DoSomethingWith(newDevice As DeviceUnderTest)
' This is where you run additional code that you would otherwise put in the 'Add()' method.
Throw New NotImplementedException
End Sub
#End Region ' Add()
#Region "Remove()"
Public Shadows Function Remove(device As DeviceUnderTest) As Boolean
Try
RemoveItem(IndexOf(device))
Catch
Return False
End Try
Return True
End Function
Protected Overrides Sub RemoveItem(index As Integer)
MyBase.RemoveItem(index)
End Sub
#End Region ' Remove()
End Class