Should I shadow or override?

1.2k Views Asked by At

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?

2

There are 2 best solutions below

2
On BEST ANSWER

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
2
On

Take a look at this question and the accepted answer. It explains the difference between the C# new & override keywords, which are, AFAIK, the same in meaning to the VB.NEt shadows & overrides.

In your case I would recommend using override. More generally, you'd better use shadows (or new in C#) only in case you know for sure why you want to do this.

If you use the shadows keyword, the users would be able to call the base type version of the method - not the one you define in your class - in case they call it through the base type reference. With the overrides your version of the method would be called in both cases.