Chapter
5
Object Orientation in C# and Visual Basic .NET
With the release of Visual FoxPro 3.0, FoxPro became
object-oriented. For those of you who have already made the leap to
object-oriented programming, you know how difficult the transition can be. Fortunately,
once you’ve learned OOP in VFP, it’s easy to learn the basics of OOP in .NET.
This chapter shows how different object-oriented features are implemented in C#
and Visual Basic .NET, while providing a comparison to Visual FoxPro’s
object-orientation.
By its very nature, this chapter is one of the more
controversial in this book. The two previous chapters were devoted to the
basics of C# and Visual Basic .NET syntax, but this chapter moves into the meatier
topic of object-orientation, providing a side-by-side comparison of the two
languages. Many of you may use the information in these chapters to decide
which .NET language to choose—and choice of language is often a religious
issue!
As in the previous chapters, I’ll point out the differences
in C# and VB .NET and offer some editorial comments on the approach I think is
better. Although both languages compile down to the same intermediate language
(MSIL), they implement .NET’s object-oriented features a little differently—and
in some cases, one language has object-oriented features not available in the
other language. Throughout this chapter, I’ll draw comparisons to Visual
FoxPro’s object-oriented features so you can leverage your existing knowledge of
OOP.
Where do you put your code?
Visual FoxPro allows you to place code in class
methods, in functions or procedures stored in PRG files, or as procedural code
stored in PRG files.
In contrast, all code in C# must be placed in classes. This
is similar to other pure object-oriented programming languages, such as Java
and SmallTalk that impose more discipline
on developers.
Visual Basic .NET takes an approach more like Visual FoxPro,
in allowing you to place code and variables in either classes or modules.
Similar to a class, a module is derived from the System.Object class and used
to encapsulate items contained within it. The main differences between a class
and a module are a class can be instantiated and implement interfaces, but a
module cannot.
Another difference is in referencing members of a class, you
must specify the name of the class followed by the member (for example,
Customer.GetCreditLimit). In contrast, members declared in a module are like
global variables and functions accessed from anywhere within your application.
By default, members of a module are shared (For details, see the “Instance and static
(Shared) members” section later in this chapter). You can compare placing code
in modules to creating global variables, functions, and procedures in a Visual
FoxPro PRG.
Are modules a “good thing” or a “bad thing”? I think the
answer to this is subjective. Personally, I tend to prefer a more “pure”
object-oriented approach, because I believe it promotes better programming
practices. However, you may prefer the convenience of being able to create
standalone functions and procedures in a Visual Basic .NET module.
Classes
At the very heart of any object-oriented language are
classes. I’ll begin by discussing the mechanics of where and how you define
classes.
In Visual FoxPro, you define classes visually in VCX files or
manually in PRG files. Defining classes in C# and VB .NET takes an approach
somewhere in between. In these languages, you can place class definitions in
source files (either .cs or .vb files), which are similar to Visual FoxPro’s
PRG files. However, Visual Studio .NET lets you easily navigate to a particular
class and a specific method in a source code file using the class and member
combo boxes at the top of the code-editing window.
The class combo box (Figure 1) contains a list of all
classes defined in a source code file. Selecting a class from this combo box
takes you to the class definition in the source code.

Figure 1. The class combo box, at the top left of
the code-editing window, contains a list of all classes defined in the source
code file.
The member combo box (Figure 2) contains a list of all
members defined for the currently selected class. Selecting a member from this
combo box takes you to the member in the source code file.

Figure 2. The member combo box at the top right
of the code-editing window contains a list of all members for the currently
selected class.
As you manually page or arrow up/down in the source code
file, the selected items in these boxes change to reflect your current location
in the source code—a nice feature.
Defining classes
In Chapter 3, “Introduction to C#”, and Chapter 4,
“Introduction to Visual Basic .NET”, you learned the basics of defining
classes. In this chapter I’ll review some of that information and expand on it.
Here’s an example of the most simple class definition in C#:
public class SimpleClass
{
}
And in VB .NET:
Public Class SimpleClass
End Class
In both cases, this code defines a class named “SimpleClass”.
The public keyword is
an access modifier specifying the visibility of the class. If you don’t specify
an access modifier, the visibility defaults to “internal” for C# and the
equivalent “friend” for VB .NET. Table 1 lists the access modifiers that
apply to classes.
Table 1. C# and VB .NET class access modifiers
|
C#
Access modifier
|
VB .NET
Access modifier
|
Description
|
|
public
|
public
|
Indicates no restrictions for
accessing the class.
|
|
internal
|
friend
|
Indicates the class is only accessible from code within the
same assembly where the class is defined.
|
Defining fields (member variables)
As discussed in Chapter 3, “Introduction to C#”,
variables declared at the class level are known as fields, and as discussed
in Chapter 4, “Introduction to Visual Basic .NET”, they are known as member
variables in VB .NET. I don’t want to skip mentioning this here, but check
out the corresponding chapter for details on each of these.
Defining properties
C# and Visual Basic .NET properties are similar to
Visual FoxPro properties with associated access and assign methods. They are
implemented as get and set accessor methods
containing any code you want. Here is an example of a property used to retrieve
and store the value of a private field (member variable in VB .NET).
In C#:
private int age = 99;
public int Age
{
get
{
return this.age;
}
set
{
this.age = value;
}
}
And in Visual Basic .NET:
Private _age As Integer = 99
Public Property Age() As Integer
Get
Return _age
End Get
Set(ByVal Value As
Integer)
_age = Value
End Set
End Property
In this code, the property has a get
method used to retrieve the value from a private field, and a set method that stores a
value to the private field. Notice the C# code sample takes advantage of C#’s
case sensitivity, by naming the private field age
and the property Age.
Because VB .NET isn’t case sensitive, you need to give any associated member
variable a different name than the property.

It is not required for a property to have an associated field
(member variable), although they often do. For example, rather than getting and
setting the value of a field, code within a property might read and write data
instead.
Notice in the C# sample code, the set
method uses an intrinsic parameter named value.
When client code saves a value to a property, it is stored in this intrinsic value variable. In
contrast, although the Set
method in the VB .NET sample code explicitly declares a variable named Value, you are allowed to
change the name of this variable (although I can’t think of a compelling reason
to do so).
Read-only and write-only properties
In C#, if you want to create a read-only property, all
you have to do is leave out the set
accessor method. For example:
private int
height;
public int Height
{
get
{
return this.height;
}
}
You do the same thing in Visual Basic .NET, but you must also
add the ReadOnly keyword
to the property definition:
Private _height As Integer
Public ReadOnly Property Height() As Integer
Get
Return Me._height
End Get
End Property
If you want to create a write-only property in C#, just leave
out the get accessor
method. You do the same thing in Visual Basic .NET, but you must also add the WriteOnly keyword to the
property definition.
Defining methods
A class doesn’t do much without methods. Here’s an
example of a simple method declaration
in C#:
public void SimpleMethod()
{
}
And in Visual Basic .NET:
Public Sub SimpleMethod()
End Sub
This code defines a method named “SimpleMethod” that returns
nothing (void, in C#). Both
C# and VB .NET require parentheses after the name of the method. As shown in
the next section, these parentheses contain a list of parameters passed to the
method. In this case, even though there are no parameters, you must still add
the parentheses as a placeholder.
Here’s an example of a C# method that returns a boolean
value:
public bool SimpleMethodBool()
{
return true;
}
This is exactly the same as the previous C# method
declaration, except I specified the return value is boolean rather than void,
and I added a line of code that returns a boolean value. This is extremely
consistent syntax.
Now here’s the same method in Visual Basic .NET:
Public Function SimpleMethodBool() As Boolean
Return True
End Function
Notice the method is declared as a function rather than a
subroutine (Sub) and has an
additional As clause
specifying the type of the return value. What’s going on here?
In VB .NET, to specify a method return nothing, you must
declare it as a subroutine (Sub).
If a method returns a value, you must declare it as a Function and use the As clause to specify the
return value type.
In all the methods shown above, the public
keyword is an access modifier specifying the class visibility. Table 2
lists all access modifiers for C# and VB .NET members.
Table 2. C# and VB .NET class member access
modifiers
|
C#
Access modifier
|
VB .NET
Access modifier
|
Description
|
|
public
|
Public
|
No restrictions for accessing
the member.
|
|
protected
|
Protected
|
The member is only accessible from within the class or
from classes derived from the class.
|
|
internal
|
Friend
|
The member is only accessible from code within the assembly
where the member is defined.
|
|
protected internal
|
Protected Friend
|
The member is only accessible from within the class or
from code within the assembly where the member is defined.
|
|
private
|
Private
|
The member is only accessible within the containing class.
|
Specifying method parameters
There are a few different kinds of method parameters in
C# and VB .NET (Table 3) described in the following sections.
Table 3. C# and VB .NET method parameters
|
C# parameter keywords
|
VB .NET
Access modifier
|
Description
|
|
(no keyword needed)
|
ByVal
|
Value parameter—the default
for C# and VB .NET
|
|
reference
|
ByRef
|
Reference parameter
|
|
params
|
ParamArray
|
Parameter array
|
|
out
|
Not required
|
Output parameter
|
|
n/a
|
Optional
|
Optional parameter
|
Value parameters
Just as in Visual FoxPro, the default parameter type in
both C# and Visual Basic .NET is a value parameter. In practical terms, if
the method you call changes the value of the parameter, the value is not
changed in the calling method. Here’s an example of a method with a value
parameter in C#:
public void ValueParam(int age)
{
age++;
}
And in Visual Basic .NET:
Public Sub ValueParam(ByVal age As Integer)
age = age + 1
End Sub
In C#, if you don’t specify otherwise, the parameter is
passed by value. In VB .NET, if you don’t specify the kind of parameter, Visual
Studio .NET automatically inserts the ByVal
keyword for you.
Reference parameters
When you pass a parameter by reference, if the method
changes its value, the value is also changed in the calling method. Here’s an
example using a reference parameter in C#:
public void ReferenceParam(ref int age)
{
age++;
}
And in Visual Basic .NET:
Public Sub ReferenceParam(ByRef age As Integer)
age += 1
End Sub
In C#, if a method accepts a reference parameter, you must
specify in the method call that you are passing the value by reference:
PtDemo.ReferenceParam(ref age);
In Visual Basic .NET, you don’t have to specify you’re
passing the value by reference:
PtDemo.ReferenceParam(Age)
Array parameters
You can pass a variable number of parameters to a C# or
VB .NET method by declaring an array parameter. Within the method body, you can
use a foreach loop to
access all items in the passed array.
In C#:
public void ArrayParam(params int[] ages)
{
string AgeMsg =
"";
foreach (int i in ages)
{
AgeMsg += i + ":
";
}
MessageBox.Show("Ages:
" + AgeMsg, "Array Parameter demo");
}
In Visual Basic .NET:
Public Sub ArrayParam(ByVal ParamArray ages() As
Integer)
Dim AgeMsg As String =
""
Dim i As Integer
For Each i In ages
AgeMsg +=
i.ToString() & ": "
Next i
MessageBox.Show("Ages: " & AgeMsg, "Array Parameter
demo")
End Sub 'ArrayParam
Output parameters
C# has output parameters—a parameter type not available
in Visual Basic .NET. An output parameter is similar to a reference parameter,
but it allows you to pass a variable to a method without first specifying an
initial value. If you remember from Chapter 3, “Introduction to C#”, in an
effort to encourage good programming practices, C# requires you to specify a
value for all variables before using them. Output parameters are the one
exception to the rule. To demonstrate, here’s a C# method that declares a
single output parameter:
public void OutParam(out int age)
{
age = 39;
}
And here’s an example of code calling this method:
int JackBennysAge;
PtDemo.OutParam(out JackBennysAge);
Notice this code declares the variable JackBennysAge, but
never stores an initial value. So why aren’t output parameters available in VB
.NET? Because VB .NET does not require you to initialize variables (although
it’s a good idea to specify initial values anyway!).
Optional parameters
Visual Basic .NET has a type of parameter not available
in C#—optional parameters. Optional parameters provide a way to specify a
particular parameter that is not mandatory. When declaring an optional
parameter, you must specify a default value in case the caller doesn’t pass a
value for the optional parameter. For example, here’s a VB .NET method that
declares a single optional parameter with a default value of 50:
Public Sub OptionalParam(Optional ByVal age As Integer =
50)
At first, optional parameters might seem like a great
feature. However, you should probably avoid using them! One reason is C# does
not recognize optional parameters—it sees them as mandatory, just like every
other parameter. This is an important consideration if you anticipate C# clients
may be accessing your code. Optional parameters can also introduce problems if
you ever decide to change the default value of the optional parameter. For
details, see the MSDN article “Exploiting New Language Features of Visual Basic
.NET, Part 2” (http://msdn.microsoft.com/msdnmag/issues/01/08/instincts/instincts0108.asp).
In reality, avoiding optional parameters is not a real loss.
You can actually accomplish the same thing by means of overloaded methods.
Overloaded methods
In Visual FoxPro, all class methods must have unique
names. You may be surprised to learn this is not true in C# or Visual Basic .NET.
Both languages allow you to create multiple methods with the same name—as long
as the number and type of parameters is different. For example, the following
code defines a class with two methods, both named “DisplayMessage”.
In C#:
public class OverloadedMethodsDemo
{
public void
DisplayMessage(string message, string caption)
{
MessageBox.Show(message,
caption);
}
public void
DisplayMessage(string message)
{
this.DisplayMessage(message,
"Application Message");
}
}
And in Visual Basic .NET:
Public Class OverloadedMethodsDemo
Public Overloads Sub
DisplayMessage(ByVal message As String, _
ByVal caption As
String)
MessageBox.Show(message, caption)
End Sub 'DisplayMessage
Public Overloads Sub
DisplayMessage(ByVal message As String)
Me.DisplayMessage(message, "Application Message")
End Sub 'DisplayMessage
End Class 'OverloadedMethodsDemo
Although these methods have the same name, they have a
different signature. In object-oriented terminology, the word signature
refers to the type and order of a method’s parameters. In this case, the first
overload of the DisplayMessage method accepts two string parameters—one named
“message” and the other named “caption”. The second overload accepts only one string
parameter named “message”.
When a client calls the DisplayMessage method, the compiler
examines the parameters passed to the method and determines which overloaded
method should be called. For example, the following code instantiates the OverloadedMethodsDemo
class. The second line of code calls the DisplayMessage method with a single
string parameter, and the third line of code calls the method with two string
parameters.
In C#:
OverloadedMethodsDemo OverloadDemo = new
OverloadedMethodsDemo();
OverloadDemo.DisplayMessage("Overloaded methods are
great!");
OverloadDemo.DisplayMessage("Overloaded methods are
great!", "Overload demo");
In Visual Basic .NET:
Dim OverloadDemo As New OverloadedMethodsDemo()
OverloadDemo.DisplayMessage("Overloaded methods are
great!")
OverloadDemo.DisplayMessage("Overloaded methods are
great!", "Overload demo")
The compiler is satisfied with these two calls because there
are overloaded methods matching each set of parameters. However, if you try to
call the DisplayMessage method with an incorrect number of parameters (for
example, no parameters, more than two parameters, or parameters that are not
string types), the compiler displays an error message.
Visual Studio .NET’s IntelliSense lets you know if a method
you are calling is overloaded. For example, Figure 3 shows the popup
displayed by VS .NET when entering code that calls the DisplayMessage
overloaded method.

Figure 3. When you enter code that calls an
overloaded method in Visual Studio .NET’s code editor, a popup displays showing
details of the overloaded methods.
So, where would you use overloaded methods? When you have a
method with optional parameters, you should create overloaded methods
representing the different variations of parameters that can be passed to the
method. This is much cleaner than having a single method checking which
parameters have been passed.
Constructor methods
All Visual FoxPro classes possess an Init method that
automatically executes when a class is instantiated. C# and VB .NET also have
constructor methods that perform a similar function.
In C#, you declare a constructor method by adding a method
with the same name as the containing class:
public class ConstructorDemo
{
public ConstructorDemo()
{
}
}
In Visual Basic .NET, you declare a constructor by adding a
New method to the class definition:
Public Class ConstructorDemo
Public Sub New()
End Sub
End Class
I actually prefer the VB .NET convention, because it’s easier
to quickly identify a constructor that’s consistently named the same.
Notice in both code samples that neither constructor
specifies a return value. This is because .NET constructors are not allowed to
return values unlike Visual FoxPro where you can return a boolean False to
prevent a class from instantiating.
Constructors with parameters
As in Visual FoxPro, you can specify parameters for
constructor methods in .NET. This allows you to pass values to a class when it
is first instantiated.
Here’s an example in C#:
public class ConstructorDemo
{
private string
connectString;
public
ConstructorDemo(string connect)
{
this.connectString =
connect;
}
}
And in Visual Basic .NET:
Public Class ConstructorDemo
Private connectString
As String
Public Sub New(ByVal
connect As String)
Me.connectString =
connect
End Sub
End Class
In this code, the value passed in the constructor is used to
initialize the value of a private field. If you don’t explicitly declare a
constructor, a default constructor is automatically provided.
Here is an example of passing a value to the constructor of a
class when it is instantiated.
In C#:
ConstructorDemo ConstructDemo = new
ConstructorDemo("server=(local);uid=sa;pwd=;database=Northwind;");
And in Visual Basic .NET
Dim ConstDemo As _
New
ConstructorDemo("server=(local);uid=;pwd=;database=NorthWind;")
As
with other methods, you can also create overloaded constructor methods. Based
on the parameters you pass when instantiating a class, the appropriate
constructor is called.
Destructor methods
Visual FoxPro classes have a Destroy method that
executes when an object is released. Typically you place code in this method to
perform cleanup for the object. This works well because you have complete
control over when an object is destroyed in Visual FoxPro.
In contrast, .NET has something called non-deterministic
finalization. This means you don’t have explicit control over when an
object is destroyed. When the last reference to a .NET object is released, the
object itself is not released from memory. The object is not released until the
next time the common language runtime’s garbage collector runs (see the
“Garbage collection” section later in this chapter for details).
In both C# and Visual Basic .NET classes, you can add a
Finalize method that executes when the object is destroyed. Just remember you
can’t determine when this method is executed.
Class inheritance
One key feature of object-orientation is class
inheritance, also known as implementation
inheritance. C# and Visual Basic .NET both have single inheritance, meaning
a class can only have one parent class. In .NET, the term base class is used in place of Visual FoxPro’s “parent
class”. Personally, I prefer the term “parent class” because it’s more
descriptive and more readily understood.
Specifying a base class
When you define a class in C# or VB .NET, if you don’t
specify otherwise, its default base class is the .NET Framework’s System.Object
class. Here is an example showing how to specify a base class.
In C#:
public class BaseClassDemo : Component
{
}
In Visual Basic .NET:
Public Class BaseClassDemo
Inherits Component
End Class
This code defines a
class named BaseClassDemo derived from the .NET Framework’s Component class
(System.ComponentModel.Component). In C#, you declare a base class by placing a
colon followed by the base class name (:
Component) at the end of the first line of the class declaration.
In Visual Basic .NET, you place the keyword Inherits
followed by the base class name on the second line of the class declaration.
Inheritance works the same way in .NET as it does in Visual
FoxPro. A subclass inherits all members (properties, events, methods, and
fields) from its base class, including implementation code.
Overriding inherited methods
At times, you may want a class to override an inherited
method. In Visual FoxPro, the simple act of placing code in a method causes the
method to be overridden. Unfortunately, in VFP all it takes is a single space
character to unintentionally override a parent method.
You can “accidentally” override a method in C# and Visual
Basic .NET by creating a method in a class with the same name and signature as
an inherited method. For example, the following code declares a class named
MyBaseClass with a single method named DisplayMessage. It also declares a
subclass of MyBaseClass named “OverrideMethodDemo” that contains a duplicate
DisplayMessage method.
In C#:
public class MyBaseClass
{
public void
DisplayMessage()
{
MessageBox.Show("Base
class method!", "Override demo");
}
}
public class OverrideMethodDemo : MyBaseClass
{
public void
DisplayMessage()
{
MessageBox.Show("Subclass
method!", "Override demo");
}
}
In Visual Basic .NET:
Public Class MyBaseClass
Public Sub DisplayMessage()
MessageBox.Show("Base class method!", "Override
Demo")
End Sub
End Class
Public Class OverrideMethodDemo
Public Sub
DisplayMessage()
MessageBox.Show("Subclass method!", "Override Demo")
End Sub
End Class
When you run this code, the OverrideMethodDemo.DisplayMessage
method is executed, but the base class method is not. In reality, this is not a
legal way to override a method in either C# or Visual Basic .NET. In both
languages, the compiler catches this error and displays it as a warning (Figure
4).

Figure 4. The C# and VB .NET compilers display a
warning if you create a method in a class with the same name and signature as
an inherited method.
The following code demonstrates the proper syntax for overriding
methods by using the override
keyword (C#) or the Overrides
keyword (VB .NET) in the method declaration.
In C#:
public class
MyBaseClass
{
public virtual void DisplayMessage()
{
MessageBox.Show("Base class
method!", "Override demo");
}
}
public class OverrideMethodDemo : MyBaseClass
{
{
MessageBox.Show("Subclass
method!", "Override demo");
}
}
And in Visual Basic .NET:
Public Class MyBaseClass
Public Overridable Sub
DisplayMessage()
MessageBox.Show("Base class method!", "Override
Demo")
End Sub
End Class
Public Class OverrideMethodDemo
Inherits MyBaseClass
MessageBox.Show("Subclass method!", "Override Demo")
End Sub
End Class
When you instantiate the OverrideMethodDemo class and run its
DisplayMessage method, the code in the OverrideMethodDemo subclass is executed,
but the DisplayMessage method in the parent is not executed.
Virtual (Overridable) methods
Virtual methods can be overridden by a subclass. In
Visual FoxPro, all methods are virtual because you can override any inherited
public or protected method simply by placing code in the method of a subclass.
There is no such thing as a “non-virtual” method in Visual FoxPro.
In contrast, methods are non-virtual by default in C# and VB
.NET and cannot be overridden. In order to override a method, it must be
specifically marked as virtual
(C#) or Overridable (VB
.NET) in the base class. If you look closely at the code in the previous
section, you will see the DisplayMessage method in MyBaseClass was marked virtual (Overridable for VB .NET).

If you override a virtual method, the method in the subclass
marked “override” is automatically virtual too.
Extending inherited methods
More often than not, you extend rather than completely
override an inherited method. In Visual FoxPro you accomplish this by placing
code in a method, then issuing a DODEFAULT command. You can run DODEFAULT
first, before executing your subclass code, or you can run your code first, and
then issue a DODEFAULT.
To call a base class method in C#, you use the base keyword:
public class CallBaseMethodDemo : MyBaseClass
{
public override void
DisplayMessage()
{
MessageBox.Show("Subclass
method!", "Call base method demo");
base.DisplayMessage();
}
}
To call a base class method in VB .NET, you use the MyBase keyword:
Public Class CallBaseMethodDemo
Inherits MyBaseClass
Public Overrides Sub
DisplayMessage()
MessageBox.Show("Subclass
method!", "Call base method demo")
MyBase.DisplayMessage()
End Sub
End Class
In this example, code first executes in the subclass method
and afterwards calls the base class method. You can easily reverse this order
by placing the call to the base class first in the subclass method.
Polymorphism and virtual methods
Visual FoxPro is a weakly typed language, so you don’t
specify the types of variables. You simply declare a variable and instantiate
an object. For example:
x = CREATEOBJECT("MyClass")
As you’ve already seen, when instantiating an object in C#
and in Visual Basic .NET,
you always declare the type of the variable that holds a reference to the
object (assuming
VB .NET’s Option Strict is “On”). For example, the following code declares a
variable
named “ClientObj” of the type Client, and then stores a new instance of the
Client class into the variable.
In C#:
Client ClientObj;
ClientObj = new Client();
And in Visual Basic .NET:
Dim Client As ClientObj
ClientObj = New Client()
In this example, the code declares a variable of a specific
type, and then instantiates an object from that type—no surprises here.
However, in both C# and VB .NET, when you declare a variable
of a particular type it can also hold a reference to any subclass of that type.
Take for example the class hierarchy shown in Figure 5, which shows
Client and Invoice classes derived from the ABusinessObject class.

Figure 5. When you declare a variable of a
particular type it can also hold a reference to any subclass of that type.
Given this hierarchy, you can declare a variable of type
ABusinessObject and then store a reference to either the Client or Invoice
object in this variable.
In C#:
ABusinessObject BizObj;
BizObj = new Client();
BizObj = new Invoice();
And in Visual Basic .NET:
Dim BizObj As ABusinessObject
BizObj = New Client()
BizObj = New Invoice()
This technique allows you to write more generic code that
works with families of objects, making use of object-oriented polymorphism
rather than coding to a specific class.
Hiding inherited methods
So far, you’ve learned about overriding and extending
inherited methods. However, there are other situations where you may want to
completely hide an inherited method and redeclare it.
To hide an inherited method in C#, use the new keyword in the method
declaration:
public class HideMethodDemo : MyBaseClass
{
public new void
DisplayMessage()
{
MessageBox.Show("Subclass
method!", "Hide method demo");
}
}
To hide an inherited member in Visual Basic .NET, use the shadows keyword in the
method declaration:
Public Class HideMethodDemo
Inherits MyBaseClass
Public Shadows Sub
DisplayMessage()
MessageBox.Show("Subclass method!", "Hide method
demo")
MyBase.DisplayMessage()
End Sub
End Class
In what situations might you choose to completely hide an
inherited method? First of all, you can use it to override a method not marked
as virtual (or Overridable). Although I
said earlier only virtual methods can be overridden, you can get around this rule
by redeclaring a method with the new
or shadows keyword.
Be
judicious when deciding to hide an inherited method. If a base class method has
not been marked as “virtual”, the developer may have a good reason for not
allowing you to override the method. Test your code well!
For example, the following code declares a class named
BaseClass with a single non-virtual method named “DisplayMessage”. It then
declares a subclass of HideMethodBase named “HideMethodDemo” that redeclares
the DisplayMessage method. This method even contains a call to the base class
DisplayMessage method!
In C#:
public class HideMethodBase
{
public void
DisplayMessage()
{
MessageBox.Show("Base
class method!", "Override demo");
}
}
public class HideMethodDemo : HideMethodBase
{
{
MessageBox.Show("My
new method", "Hide method demo");
base.DisplayMessage();
}
}
In Visual Basic .NET:
Public Class HideMethodBase
Public Sub
DisplayMessage()
MessageBox.Show("Base class method!", "Override
demo")
End Sub
End Class
Public Class HideMethodDemo
Inherits HideMethodBase
'
Hide the DisplayMessage method in the base class
MessageBox.Show("My new method", "Hide method demo")
MyBase.DisplayMessage()
End Sub
End Class
There’s one “gotcha” when hiding an inherited method in this
way. If you use the polymorphic trick of declaring a variable of the type
HideMethodBase, but you actually instantiate an instance of the HideMethodDemo
subclass instead, you get unexpected behavior when calling the DisplayMessage
method.
Here’s this scenario in C#:
HideMethodBase HideBase = new HideMethodDemo();
HideBase.DisplayMessage();
And in Visual Basic .NET:
Dim HideBase As HideMethodBase = New HideMethodDemo()
HideBase.DisplayMessage()
When you run this code, rather than calling the
DisplayMessage method belonging to the HideMethodDemo class, it calls the
DisplayMessage method belonging to the HideBase base class instead! This is opposite
of the behavior you might expect, so you need to write code with this in mind.
Another good example of a scenario where you can hide an
inherited method involves third-party .NET components. Say you purchase a
third-party component, subclass it, and add a custom method called
PrintMessage. What happens if the company who created the component releases a
new version and adds their own PrintMessage method? This leaves you with two
choices. You can rename your custom method, but you may have countless lines of
code in your applications calling the PrintMessage method and they all need to
change.
Another option is to hide the newly inherited method causing
the problem. You can then add a custom method to your subclass that calls it in
the base class.
Here’s the solution shown in C#:
public class MyBaseClass
{
public virtual void
PrintMessage()
{
MessageBox.Show("Printing
message!", "Hide method demo");
}
}
public class HideMethodDemo : MyBaseClass
{
// Hide the PrintMessage
method in the base class
{
MessageBox.Show("Hiding
the inherited method!", "Hide method demo");
}
// Create a custom method
that calls the base class method
public void PrintMsg()
{
}
}
And in Visual Basic .NET:
Public Class MyBaseClass
Public Overridable Sub
PrintMessage()
MessageBox.Show("Printing message!", "Hide method
demo")
End Sub
End Class
Public Class HideMethodDemo
Inherits MyBaseClass
'
Hide the PrintMessage method in the base class
MessageBox.Show("Hiding the inherited method!", "Hide
method demo")
End Sub
' Create a custom
method that calls the base class method
Public Sub PrintMsg()
End Sub
End Class
In this code, the HideMethodDemo class hides the PrintMessage
method in the base class. It then declares a method named PrintMsg that calls
PrintMessage method in the base class.
Preventing inheritance
As mentioned in the section “Virtual (Overridable)
Methods”, C# and VB .NET methods are non-virtual by default, meaning they
cannot be overridden in subclasses. In contrast, methods marked as “virtual”
can be overridden.
There may be cases where you override a virtual method in a
base class, but you don’t want other subclasses to override the method in your
class. You can prevent someone from overriding your method by marking it as sealed (C#) or NotOverridable (VB .NET).
For example, the
following code declares a base class named “PreventInheritanceBase” containing
a single virtual method named “DisplayMessage”. It also declares a subclass of
PreventInheritanceBase named “PreventInheritanceSubclass” that marks the DisplayMessage
method as sealed. This prevents subclasses of PreventInheritanceSubclass from
further overriding this method.
In C#:
public class PreventInheritanceBase
{
public virtual void
DisplayMessage()
{
MessageBox.Show("This
is a virtual method!", "Prevent inheritance demo");
}
}
public class PreventInheritanceSubclass : PreventInheritanceBase
