Search code examples
vb.netinheritanceoverridingshadows

Should I shadow or override?


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?


Solution

  • 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