The Overloads, Overrides, and Shadows Keywords in VB.NET – Part 2

(From an article I originally wrote in 2004)

Part 2

Introduction

This series covers advanced topics and is not intended to be an exhaustive treatment of the subjects discussed. My intention is to provide the reader with a better understanding of the Overloads, Overrides, and Shadows keywords. Where necessary, I will refer the reader to other sources for more details. If you’re a VB.NET programmer who writes software components intended for use by other programmers or applications that can be extended by other programmers, or if you use third party components or extend components written by others, you will certainly want to become more familiar with these keywords as they will allow you to leverage more of the power and flexibility built into an object oriented language like VB.NET.
Note: This series is applicable to VB.NET programmers only. C# provides it’s own flavor of support for member hiding (shadowing), virtual functions, and overloading. And since there are significant differences in the C# implementation, here we’re discussing only VB.NET.

Also, in these articles I use the word “method” to mean any procedure in VB.NET (i.e., Subs, Functions, and Property procedures).

In Part One of this series I discussed why you, as a VB.NET programmer, should want to learn about Overloading, Overriding, and Shadowing in VB.NET and the related keywords used to implement these concepts. In this article we’ll focus our attention on the Overloads keyword.

The Overloads keyword.

Overloading allows you to write a method that has the same name but a different signature as one or more other methods where each are accessible from the same or different scope.

Overloading is often described as having “different versions” of the same method and it allows you to make your code more readable and easier to use. To explicitly overload a method you must use the Overloads keyword. But, in VB.Net, you can also implicitly overload a method from within the same class as in the example below.

Overloaded methods
(here we show different versions of the same method sitting side by side in the same class).

Public Class A
    Public Function AddTwoNumbers(ByVal N1 As Integer,
          ByVal N2 As Integer) As Integer
        Return N1 + N2
    End Function
    Public Function AddTwoNumbers(ByVal N1 As Single,
          ByVal N2 As Single) As Single
        Return N1 + N2
    End Function
    Public Function AddTwoNumbers(ByVal N1 As Double,
          ByVal N2 As Double) As Double
        Return N1 + N2
    End Function
    Public Function AddTwoNumbers(ByVal N1 As Single,
          ByVal N2 As Integer) As Single
        Return N1 + N2
    End Function
    Public Function AddTwoNumbers(ByVal N2 As Integer,
          ByVal N1 As Single) As Single
        Return N1 + N2
    End Function
End Class

There are two things you should note in the above example:

  1. The last two functions are exactly the same except for the order of the parameters (this is allowed, see the rules of overloading in this article).
  2. I didn’t use the Overloads keyword to specify these methods as being overloaded methods (this is implicit overloading, and it is also allowed).

If I wanted to use the Overloads keyword to perform explicit overloading, my functions would look like this:

Public Class A
    Public Overloads Function AddTwoNumbers(ByVal N1 As Integer,
          ByVal N2 As Integer) As Integer
        Return N1 + N2
    End Function
    Public Overloads Function AddTwoNumbers(ByVal N1 As Single,
          ByVal N2 As Single) As Single
        Return N1 + N2
    End Function
    Public Overloads Function AddTwoNumbers(ByVal N1 As Double,
          ByVal N2 As Double) As Double
        Return N1 + N2
    End Function
    Public Overloads Function AddTwoNumbers(ByVal N1 As Single,
          ByVal N2 As Integer) As Single
        Return N1 + N2
    End Function
    Public Overloads Function AddTwoNumbers(ByVal N2 As Integer,
          ByVal N1 As Single) As Single
        Return N1 + N2
    End Function
End Class

Which form should you use? That depends on your preference, but using the Overloads keyword, in my opinion, tends to be more readable.

Rules of Overloading

To properly overload a method you should know the rules of overloading in VB.NET.
In VB.NET, a signature of a method is composed of the combination of its name and it’s parameter list. For each version to be considered an overloaded method, they must all have the same name and the signature of each version must be different in one or more of the following:

  1. The number of arguments
  2. The order of the arguments
  3. The data types of the arguments

Not abiding by one or more of those three rules will have the compiler complaining when you try to build your program.

Also, as I mentioned, you don’t have to use the Overloads keyword to specify an overloaded method while within the same class (see my first example earlier). The compiler will assume you are implicitly overloading the method if their signatures abide by the rules stated above (this is how C# handles overloading – there is no Overloads keyword in C#). However, if you use the Overloads keyword on one of the overloaded methods within a class, you must use it on all of them in that class (that is to say, all of those having the same name).

That’s overloading in a nutshell.
But hold on! There is much more to it than that. Such as: When should you use it? Why would you want to? What are some points to remember?
I’ll address these questions below.

When and why should you use overloaded methods?

Use overloaded methods when you have a method that performs a task and you want that method to perform the same task on different data types or a different number of variables.
In my example earlier, I used a method that added two numbers together and returned the result. I also wanted to allow the user of my function to choose whether he wants to pass two integers, two singles, two doubles, or one integer along with one single. Overloaded methods are tailor made for that requirement. The result is neat, efficient, and highly readable code. The user of my function has only to remember the one name: AddTwoNumbers. If I did not use overloaded methods, I would have had to use different names for my methods such as: AddIntToInt and AddSingleToSingle. That forces the user of my function to have to remember more than one name and maybe many, and that would be an amateurish way to program in a language that supports overloading!

Additionally, if I purchased a .NET software component to plug into my new .NET application that I’m writing, and if I saw methods named in this manner, I would immediately think the person who wrote that component is not familiar with overloading, and I would wonder what else he doesn’t know and should I be using his component?

Here are some points to keep in mind.

1. If you are deriving your own class by using a base class that is contained in a component you obtained from a vendor, you must be careful when adding members to your derived class. Picture this scenario:
If the author of the base class created several overloaded methods, you might find yourself in a situation where you want to extend those methods by providing an additional overloaded version of the method in your derived class. That way the users of your class will have both your method and the base class’s methods available to them as overloaded methods through your derived class.
But be careful and check the signatures of the overloaded methods in the base class! Why? Because if you inadvertently create an overloaded method in your derived class with the exact same signature as one of the overloaded methods in the base class (and with the same return type), you will effectively hide that version of the overloaded method in the base class – and there is no notification to you about what is happening. You would in effect be using the Overloads keyword as a form of method hiding on one of the versions of that overloaded method.
You may intend to do this if you thought you needed your own specific implementation of that version of the method while leaving the other versions also available, but if you did not intend it, you would have wasted your time coding your method and the users of your class won’t be able to take advantage of any new improvements that the author of the base class makes in his implementation. That’s something to keep in mind.

2. Be careful with your access modifiers. I used the Public modifier in my declarations, but I could have easily used another, or even mixed them up so that some used Private, others used Friend, and still others used Public. This is perfectly legal and mixing modifiers will mean that a different subgroup of the overloaded methods will be available at different scopes. Although it may not be common, if you don’t see all of the versions of an overloaded method, this may be the reason.

3. If you create a derived class and you want to overload a method that is in the base class, you must use the Overloads keyword, because the compiler can’t tell if you want to overload the method or shadow it and it will assume the Shadows keyword. In fact, if you forget the Overloads keyword, the design time environment in Visual Studio will underline the offending method and display a warning and a tool tip suggesting you use the Shadows keyword in your method declaration (unless the method in the base class is also declared as Overridable, then you’re asked to override it).
You can still compile your component, but the runtime will assume you are shadowing the method and that is how your code will behave. This can be a source of confusion for programmers trying to understand the use of the Overloads keyword, because Visual Studio directs the programmer’s attention to the Shadows keyword.
The exact message when I do this in Visual Studio reads:

function ‘AddTwoNumbers’ conflicts with function ‘AddTwoNumbers’ in the base class ‘A’ and so should be declared ‘Shadows.’

A novice would think that he must use the Shadows keyword. Not true! If your intent is to overload the method as described in this article, then make sure you use the Overloads keyword, if you intend to shadow the method, then use the Shadows keyword (shadowing is discussed in more detail in the fourth installment of this series).

In addition to those I’ve mentioned, there are other considerations when overloading methods, but MSDN covers those very well and you can find that information here: Considerations in Overloading Procedures .

Summary

We’ve covered the basics of overloading and touched on some of the issues you should be aware of when overloading methods. In the next installment we’ll continue with a discussion on overriding and the Overrides keyword. I’ll see you then!

VN:F [1.9.3_1094]
Rate this content:
Rating: 5.0/5 (1 vote cast)
The Overloads, Overrides, and Shadows Keywords in VB.NET - Part 2, 5.0 out of 5 based on 1 rating No Comments yet.
Leave a Comment