If you're starting to work with Visual Studio .NET, you'll find you have a head start when it comes to inheritance.

Here are some of the differences.

In our articles in the November and December 2003 issues, we discussed the fundamentals of object-oriented development, comparing how they're implemented in VFP and .NET. This included a broad over-view in the first article, and an in-depth look at creating methods and properties in the second article. Armed with this knowledge, you should be able to transfer it from VFP to .NET to create and use objects at a fundamental level. In this article, we're going to take a close look at the feature that traditionally made Visual FoxPro superior to languages such as Visual Basic 6: inheritance.

For VFP developers, inheritance is second nature. For developers using VS.NET who came from languages such as Visual Basic, inheritance is revolutionary. Although the implementation of the inheritance feature in VS.NET is great, I would venture to say that overall, the level of sophistication at which .NET developers use inheritance today is about the same as it was in VFP in 1996. People know it's there and how it works, but most developers aren't yet able to unleash the power inheritance provides. For VFP developers, this means you have a gigantic head start. On the other hand, there are a few details that are a bit different in Visual Studio .NET, due to .NET's strongly typed nature, which you need to be aware of.

Fundamentals

The basic idea of inheritance is relatively trivial: You can simply define a class that's "exactly like some other class." For example, you could create a Contact class, then inherit from it to create a more specialized contact, such as a Customer. Here's the VFP code for this type of scenario. First the Contact:

DEFINE CLASS Contact as Custom
  FUNCTION GetFullName() AS String
   RETURN "Egger, Markus"
  ENDFUNC
ENDDEFINE

As you can see, this is a rather simplistic Contact class, but it'll suffice for this example. Note that we created a method rather than a property for this example, because we don't want to confuse you with the different ways of creating properties in VFP and .NET (see last issue's article). But, for the most part, everything we're going to demonstrate in this first example would work pretty similarly if we used properties.

Here's the subclassed contact, used to represent customer information:

DEFINE CLASS Customer AS Contact
  FUNCTION IsValidCustomer() as Boolean
  RETURN .T.
  ENDFUNC
ENDDEFINE

Because this class is subclassed from Contact it will behave just like the contact, with the exception of the code added in the Customer class. In other words, this class has a GetFullName() method (which it derives from Contact) and the newly defined IsValidCustomer() method.

A few other things are noteworthy here. For one, we didn't specify the visibility of the method. Therefore, all the methods are visible to the outside ("public"), because that's the default in Visual FoxPro. Secondly, we specified the return type of the methods ("String" and "Boolean," respectively). This technically isn't required in VFP, but it makes the code more readable and provides benefits in COM scenarios, as well as for IntelliType (see our previous two articles for more details on this subject).

If you've read our articles in the November and December 2003 issues, you should already be familiar with the syntax required to implement the same scenario in VS.NET. First, here's the VB.NET version:

Public Class Contact
  Public Function GetFullName() As String
    Return "Egger, Markus"
  End Function
End Class

Public Class Customer
  Inherits Contact

  Public Function IsValidCustomer() As Boolean
    Return True
  End Function
End Class

As you can see, the differences between VB.NET and VFP are almost negligible. Probably the most important difference is that the Contact class doesn't specify any parent class, although the VFP version inherits from Custom. The difference isn't quite as significant as it appears, though, because the VB.NET compiler automatically assumes the class Object is the parent class. The second difference is that VB.NET uses the keyword Inherits instead of As. Also, you must place the Inherits keyword on a new line.

The C# version is similar in concept, although the syntax is slightly different:

public class Contact
{
  public string GetFullName()
  {
   return "Egger, Markus";
  }
}

public class Customer : Contact
{
  public bool IsValidCustomer()
  {
   return true;
  }
}

As you probably know by now, C# uses curly brackets to indicate the start and end of a structure, such as a class or a method. Also, C# puts the type before the method name, and doesn't require keywords such as Function or As. Then, of course, there are the semi-colons. Also, C# uses the colon instead of the As or Inherits keyword. Beyond that, the structure of the code is similar to the previous examples. (Note: If you have questions about the exact syntax, please refer to the previous two articles in this series).

Instantiating and manipulating inherited objects

Now that you created two classes in each language, you can instantiate them and call your methods. Here's the familiar VFP syntax:

LOCAL oContact as Object
oContact = CreateObject("Contact")
oContact.GetFullName()

LOCAL oCustomer as Object
oCustomer = CreateObject("Customer")
oCustomer.GetFullName()
oCustomer.IsValidCustomer()

In this example, you instantiate both objects and call all the methods each object has (we'll ignore the ones we inherit from Custom for now). You can do the same thing in VB.NET:

Dim oContact As New Contact
oContact.GetFullName()

Dim oCustomer As New Customer
oCustomer.GetFullName()
oCustomer.IsValidCustomer()

This is a rather trivial operation. In fact, you could argue that it's even easier than in VFP, but that would be nitpicky. We want to draw your attention to one detail, though: When the local variables are created ("oCustomer"), we strongly type it to be of type Customer (our class), although in the VFP version, we simply state that it was an object. The same is also true for the Contact object. In VFP, the object type is really the only option we have, because VFP doesn't consider classes and types to be the same thing. Note that we could have defined the reference to be of a certain type, even in VFP. This would have still resulted in the reference being of type Object, because that's the only type VFP knows that can store object references. Only the editor uses more specific typing in VFP to provide better IntelliSense. This is an important distinction.

Here's the C# version:

Contact oContact = new Contact();
oContact.GetFullName();

Customer oCustomer = new Customer();
oCustomer.GetFullName();
oCustomer.IsValidCustomer();

As all these examples demonstrate, Customer can do everything the Contact class supports (and then some). In our scenario, this means the Customer class features the GetFullName() method. In fact, it would be correct to say "Customer is a Contact," because our Customer class is really only a specialized version of a Contact. That's why inheritance is also known as an "Is-A relationship." In the .NET world, this is a fairly important statement because it implies that the Customer class is, in fact, the same type as a Contact class. For this reason, it would have been perfectly fine to type an instance of a Customer class as type Contact (VB.NET):

Dim oCustomer As Contact = New Customer()
oCustomer.GetFullName()

In this case, the code got a little more cluttered. We couldn't just squeeze the New keyword in between the As and the type as we could before, because the type (class) we want to instantiate is different from the local variable type.

The C# version, on the other hand, changes very little:

Contact oCustomer = new Customer();
oCustomer.GetFullName();

Either way, you now have an instance of a Customer object in memory with absolutely everything a customer object exposes, including the IsValidCustomer() method. However, here's the catch: The compiler doesn't know that, because you told it the new instance was of type Contact. Therefore, the compiler isn't aware of the IsValidCustomer() method, and will fail to compile when you try to call it. As far as the compiler is concerned, only the methods defined in the type are accessible.

Now you know why it's so important you define your variable as the type you want to use, rather than just Object. It would technically be OK to define all variables as Object, because every class ultimately inherits from a class called Object (even strings and other simple types), but you could never call any of the methods or properties on those objects, except the ones defined by the Object class.

On the other hand, sometimes you'll want to be able to store a reference to an object of unknown type. Perhaps you want to create a method that can inspect an object and find out what properties and methods it has, or what its name is. Here's an example of a similar method:

Public Function InvestigateObject(ByVal o As Object)
  _As String
  Return o.ToString()
End Function

And here's the C# version:

public string InvestigateObject(object o)
{
  return o.ToString();
}

Any object can now call these methods. This would be fine, for example:

this.InvestigateObject(oCustomer);

As you know, Customer is a Contact, and Contact is, in turn, an object. Therefore, Customer also has to be an object. And as mentioned before, this is true for any other object in .NET, including the simple types, such as strings and numbers. Therefore, this code is valid as well:

this.InvestigateObject("Hello World");
this.InvestigateObject(25);

Another example that illustrates the point would be a form manager. You could implement this as a collection of Form objects that represent each open window of an application. Because .NET is entirely based on subclassing, each instantiated form is likely to be of a different class, such as CustomerEditForm or PickProductDialog, but all these windows inherit from a basic Form class. Therefore, you can write a generic collection of forms where each item in the collection is of type Form. Now, assume you have a CustomerEditForm class that has a method such as IsCustomerValid(). Also assume this form is stored in your generic collection of form objects. As you know, you can't call that method on a reference that's of type Form because other forms don't have this particular method. So, how can you get to it if you have to? You must perform a type-cast operation. This sounds scary and difficult, but in reality, it's only scary. Here's how to do it (assuming your forms collection is called Me.Forms):

Dim oGenericForm As Form
Dim oCustomerEditForm As CustomerEditForm
oGenericForm = Me.Forms(0)
oCustomerEditForm = CType(oGenericForm, CustomerEditForm)

The most important part is the last line, which uses CType() to cast the generic form reference to the more specific CustomerEditForm type. Note you could have also written this cast in a single statement:

Dim oCustomerEditForm As CustomerEditForm = _
  CType(Me.Forms(0), CustomerEditForm)

C# uses slightly different syntax. Here, you simply identify the type to which you want to case in parenthesis before the variable name:

Form oGenericForm = (CustomerEditForm)this.Forms[0];

At this point, you could happily call the IsCustomerValid() method on the object, because internally, that method was always there. The compiler just didn't know about it. And as promised, this wasn't that difficult.

So what's so scary? Well, the scary part is that you can't be certain this.Forms[0] points to an instance of a CustomerEditForm class. It could be any form class for all you know (such as a PickProductDialog class), and if the object isn't of the type to which you're trying to cast, you crash the system. This is a scenario VFP developers are familiar with. Imagine using the Screen's Form collection to retrieve a reference to the first open form, and simply calling a method on it, assuming it's a CustomerEditForm:

_Screen.Forms(1).IsCustomerValid()

If Forms(1) wasn't of a class that had that method, you'd create a similar type of runtime crash. The idea in VFP is you just have to be careful with these things, because that's just how weakly typed languages work. .NET, on the other hand, is a strongly typed environment, and the compiler usually catches such problems at compile time. After you start performing manual casts, however, you're removing this safety net, and giving up one of .NET's greatest features.

So how can you avoid these problems? One way is to verify the type before you attempt the cast. This is also relatively easy. Here's the VB.NET version:

If TypeOf (Me.Forms(0)) Is CustomerEditForm Then
  oCustomerEditForm = CType(Me.Forms(0), CustomerEditForm)
End If

This time, the C# version is a bit easier to understand:

if (this.Forms[0] is CustomerEditForm)
{
  oCustomerEditForm = (CustomerEditForm)this.Forms[0];
}

VoilĂ ! That was much less scary and guaranteed to work at runtime. Note that each language also features additional casting operations that are more performance optimized, but these details are beyond the scope of this article.

Inheriting and overriding methods

Now you know a lot about how inherited objects behave after they're in memory, but we still have a lot to discuss about the definition of these objects. For example, you may want to override methods you inherited. Let's go back to the basic Customer class. This class inherits a method called GetFullName, which simply returns "Egger, Markus." But what if you want to change that behavior? Well, as in VFP, you can simply override that method in the subclass:

Public Class Customer
  Inherits Contact

  Public Function GetFullName() As String
    Return "Lassala, Claudio"
  End Function

  Public Function IsValidCustomer() As Boolean
    Return True
  End Function
End Class

Unfortunately, this immediately generates a compiler warning. What's wrong? Well, nothing, except the compiler is concerned the scenario might be ambiguous. Did the developer realize this completely overrides and ignores the code you had in the parent class? It could even be that the original version of the Contact class didn't have a GetFullName method, but a later version may add that, which could lead to potential conflicts with the Customer class. These are all scenarios Visual FoxPro silently ignores, but the .NET compilers want a bit more guidance.

So what did we really intend to do? In this example, we wanted to get rid of the original method and provide our own behavior. This is known as shadowing or as defining a new method. You can inform that compiler about your intention by adding a simple keyword:

Public Shadows Function GetFullName() As String
  Return "Lassala, Claudio"
End Function

As expected, things work similar in C#, but the keyword is different:

public new string GetFullName()
{
  return "Lassala, Claudio";
}

Adding the required keyword satisfies the compiler, and your code will work as intended. However, creating a new/shadow function has other implications you may or may not want. Assume your Contact class (the parent class) calls the GetFullName() method internally, as in this C# example:

public class Contact
{
  public string GetFullName()
  {
   return "Egger, Markus";
  }

  public string GetCompanyAndName()
  {
   return "EPS: " + this.GetFullName();
  }
}

This makes for a simple scenario when you instantiate the Contact class and call the GetCompanyAndName() method. The return value will be "EPS: Egger, Markus." But what happens when you instantiate the Customer class and all that same method? Based on our experience with VFP, we'd assume we overrode the GetFullName() method and, therefore, the return value would be "EPS: Lassala, Claudio." But, this isn't the case.

Using the shadows or new keyword on a method instructs the compiler to ignore the original method that happened to have the same name, and use the new method whenever you deal with the Contact class. However, whenever you deal with code in the parent class, the shadow/new method isn't supposed to accidentally change the behavior. For that reason, the original code will execute when we call GetCompanyAndName(), because that code was defined on the parent class. This is a great feature when you want to preserve the original behavior of the class and prevent code from being accidentally overridden.

Of course, you may in fact have intended to change the original behavior. In that case, you have to indicate to the compiler that you explicitly intend to override and change the original method no matter where the calling code is physically located. In C#, we do this with the override keyword:

public class Customer : Contact
{
  public override string GetFullName()
  {
   return "Lassala, Claudio";
  }
}

Confusingly, VB.NET uses an Overrides keyword (with an "s" at the end) to indicate the same desired behavior:

Public Class Customer
  Inherits Contact

  Public Overrides Function GetFullName() As String
   Return "Lassala, Claudio"
  End Function

When you compile this version, you're in for another surprise: The compiler still isn't satisfied. The complaint this time is that you can't override the GetFullName() method. This may appear strange at first (especially to VFP developers) but, it's the desired behavior. VS.NET lets you indicate whether methods can be overridden in subclasses. By default, they can't. Therefore, you have to go to the parent class and indicate that the methods are designed to be overridden in subclasses. In VB.NET, you can do this using the Overridable keyword:

Public Class Contact
  Public Overridable Function GetFullName() As String
   Return "Egger, Markus"
  End Function

The overridable keyword will probably be intuitive to you. C#'s version, on the other hand, probably isn't as natural. It's called virtual:

public class Contact
{
  public virtual string GetFullName()
  {
   return "Egger, Markus";
  }
}

The term virtual has a lot of tradition in OOP languages and has been used for a long time. It might have to do with the fact that it isn't exactly clear whether the code in the method is the code that's executed during runtime and, therefore, you could say the code isn't really there. Just a guess!

You might wonder why this isn't the default behavior. One of the answers is control. You simply want to make sure things that aren't meant to be overridden are kept safe. This is an excellent feature. In most scenarios, however, this means you'll find yourself typing virtual or overridable often.

The second answer is non-virtual methods perform better. Let's take a look at the task the compiler has to perform when it encounters the Contact class: First, the compiler has to generate the compiled version of the GetFullName() method. Then, it encounters the GetCompanyAndName() method, which contains a call to the GetFullName() method. This is no problem, because the compiler already has the code that represents that method and merges it right in (the simplified version). Later, the compiler creates the compiled version of the Customer class, which doesn't have additional code for GetCompanyAndName(), so the compiler never worries about that method. When the Customer class is being used, the runtime environment realizes that Customer inherits from Contact, and also instantiates a Contact object behind the scenes. Whenever you execute the inherited GetCompanyAndName() method on the Customer object, the behind-the-curtain Contact objects will be called. This is where the trouble starts because the code compiled for that method simply runs the original GetFullName() code that was merged in, unaware that it's really being called on behalf of the Customer object.

The Contact object has to check whether it's being called on behalf of another object (such as your subclassed Customer object). If so, it needs code that checks whether the customer object has an overridden GetFullName() method. If it finds one, that code has to be executed. Otherwise, it can proceed with its own (original) version. This then results in the behavior you'd expect. But, as you can tell, there's a lot of extra code that has to run to find the overridden version. Therefore, virtual methods are slower.

By the way, override-control not only exists for methods, but also for entire classes. Contrary to methods, you can inherit from classes by default, but you can change this using the sealed (C#) and NotInheritable (VB.NET) keywords:

Public NotInheritable Class Contact
End Class

public sealed class Contact
{
}

You may want to seal classes for security purposes or architectural reasons. (However, sealing isn't truly secure because malicious developers can get access to the inner workings of all classes using a technique called Reflection.) Another reason is sealed classes perform better than non-sealed classes.

But, let's get back to the discussion about overridden methods and wrap up a few loose ends. So far, you've overridden complete methods, but you haven't seen a scenario that preserves the original code in addition to the new code. In VFP, you can do this using the DoDefault() function:

DEFINE CLASS Customer AS Contact
  FUNCTION GetFullName() AS String
   LOCAL cOriginalName as String
   cOriginalName = DoDefault()
   RETURN cOriginalName + " and Lassala, Claudio"
  ENDFUNC
ENDDEFINE

DoDefault() executes the original behavior wherever the call to DeDefault() occurs in the new method. You can put your own code before or after the call to DoDefault(), or both. The same behavior is available in .NET. Here's the VB.NET version:

Public Class Customer
  Inherits Contact

  Public Overrides Function GetFullName() As String
    Dim sOriginalName As String
    sOriginalName = MyBase.GetFullName()
    Return sOriginalName + " and Lassala, Claudio"
  End Function
End Class

The MyBase keyword points to the behind-the-curtain instance of a Contact object. You can call its method of the same name as the current method. The same concept applies in C#. The only difference is the keyword, which C# calls base:

public class Customer : Contact
{
  public override string GetFullName()
  {
   string sOriginalName;
   sOriginalName = base.GetFullName();
   return sOriginalName + "Lassala, Claudio";
  }
}

That's it. Not too many surprises here.

Constructors

The same concept applies to almost all methods, with the exception of the constructors (think of constructors as .NET's equivalent of VFP's Init() method, although there are a few differences). Constructors are special because the call to the base class' code has to happen in the first line. If the call is omitted in the code, it will be made automatically (a difference that only matters if the constructor receives parameters). Considering .NET instantiates the behind-the-curtain instance of the parent class (as we discussed earlier), this is no surprise. The objects are instantiated (invisibly) and, therefore, the constructor has to run. Whenever that constructor has parameters, however, things are a bit tricker. This may be easier to explain in a simple example. Say you added the following constructor to your Contact class (VB.NET's constructors are methods called New):

Public Class Contact
  Sub New(ByVal sText as String)
   MsgBox(sText)
  End Sub

You can now instantiate the object like this:

Dim oContact as new Contact("Hello World!")

Then, add a constructor to the inherited class:

Public Class Customer
  Inherits Contact

  Sub New(ByVal sText As String)
   MyBase.New(sText)
   MsgBox(sText)
  End Sub

The important part here is the call to MyBase.New(), which happens as the first line in this constructor. Everything else, such as this example, would be invalid:

Public Class Customer
  Inherits Contact

  Sub New(ByVal sText As String)
   MsgBox(sText)
   MyBase.New(sText)
  End Sub

Also, omitting the call to MyBase.New() isn't an option because, as we discussed above, the .NET runtime environment instantiates a behind-the-curtain copy of the Contact object. But, to create that object, you have to pass a parameter to its constructor or the instantiation of that object will fail. And, because the runtime can't just make up an arbitrary parameter value, the call to Mybase.New() is required to provide that parameter. On the other hand, if your constructor didn't require any parameters, .NET could just perform the instantiation of the Contact object automatically; no call to the default behavior would be required.

Unfortunately, the inability to make the call to the parent class' code anywhere but in the first line is limiting. There's no way to set the object's field or property values before the settings occur in the parent class. This means if the code that runs in the constructor requires certain settings (such as the connection string needed to connect to a database) you can't reconfigure these settings in a subclass' constructor. It's annoying, but there are ways around this. You can add a virtual method called Configure to your objects, which the constructor of the parent class can call, but which can be overridden in subclasses. Here's an example:

public class Class1
{
  protected string sConnectionString = "";

  public Class1()
  {
   this.Configure();
   // Connect to the database right here
  }

  protected virtual void Configure()
  {
  }
}

public class Class2
{
  protected override void Configure()
  {
   This.sConnectionString = "MyConnectionString";
  }
}

In C#, the requirement to call the parent class' constructor in the first line is even more obvious. In fact, you can't use the base reference in the constructor's code. Instead, you have to use a specialized syntax for this purpose. First, the parent class:

public class Contact
{
  public Contact(string sText)
  {
   MessageBox.Show(sText);
  }
}

Note that the name of the constructor in C# is identical to the name of the class. Therefore, the name of the constructor in the subclass will be different from the name used in the parent class. The syntax to invoke the parent class' constructor is a little unusual:

public class Customer : Contact
{
  public Customer(string sText) : base(sText)
  {
   MessageBox.Show(sText);
  }
}

The call to the base functionality happens outside the method's body using the ": base()" syntax.

Another aspect of constructors that's unusual from a VFP point of view is that constructors aren't automatically inherited. This isn't immediately obvious for classes that don't define a special constructor, because the compiler automatically creates a constructor with no parameters if you don't specify one. However, if you create a constructor (like the one above) that takes a single parameter, you also have to define a constructor on the subclass. Otherwise, a compiler error occurs. This is unexpected because you would think a subclass behaves exactly like the parent class, but unfortunately, this isn't true for constructors. This is particularly annoying whenever you have classes that are inherited from on a frequent basis, especially when the constructor has multiple overloads, which all have to be specified manually. This certainly ranks high on the list of annoying .NET quirks.

Inheritance and overloading

One final aspect of method inheritance that's worthy of a short discussion is method overloading, and method signatures in general. As we've discussed in previous articles, .NET identifies methods by signature (this is the name of the method, plus the number and types of parameters), rather than by method name, as VFP does. This also means that to override a method, the new version has to exactly match the parent method's signature. In other words, this is a valid override of the GetFullName() method of the Contact class:

public class Customer : Contact
{
  public override string GetFullName()
  {
   return "Lassala, Claudio";
  }
}

On the other hand, this wouldn't be an override:

public class Customer : Contact
{
  public override string GetFullName(bool LastNameFirst)
  {
   if (LastNameFirst)
   {
    base.GetFullName();
   }
   else
   {
    return "Markus Egger";
   }
  }
}

There's no GetFullName() method with a single Boolean parameter in the Contact class. Therefore, you can't override it or call base method. In fact, this would simply be an overload -- a new method with the same name but a different number of parameters -- that appears in addition to the original method. Both methods can coexist if you define the new method without the override keyword:

public class Customer : Contact
{
  public string GetFullName(bool LastNameFirst)
  {
   if (LastNameFirst)
   {
    this.GetFullName();
   }
   else
   {
    return "Markus Egger";
   }
  }
}

You can still make calls to the parameterless version because it coexists with the newly defined overload. The original method is simply a method like any other that you can call using the "this" pointer. This also means all calls to GetFullName() without parameters would still get the original behavior. This is the desired behavior. Otherwise, all calls to GetFullName() that didn't specify a parameter would crash, because they fail to provide the parameter needed by the new version.

Inheriting properties and fields

So far, we've conveniently ignored the fact that properties and fields are inherited just like methods. What complicated the explanation of this is that .NET differentiates between fields (the variables that store values) and properties (the means to access values, such as the values defined in fields). We provided a detailed explanation of the difference between properties and fields in our last article. This time, we'll focus on how inheritance influences these two concepts. Let's start with fields. You can define simple fields like this (VB.NET):

Public Class Contact
  Protected sFirstName As String = "Markus"
  Protected sLastName As String = "Egger"

  Public Overridable Function GetFullName() As String
    Return Me.sLastName + ", " + Me.sFirstName
  End Function
End Class

The C# version is similar:

public class Contact
{
  protected string sLastName = "Egger";
  protected string sFirstName = "Markus";

  public virtual string GetFullName()
  {
   return this.sLastName + ", " + this.sFirstName;
  }
}

Both versions define two fields on the class that aren't visible to the outside world (protected) and assign a value immediately. Both examples also use these two fields in the GetFullName() method. These fields aren't yet exposed as properties. You can do this with a few extra lines:

Public Class Contact
  Protected sFirstName As String = "Markus"
  Protected sLastName As String = "Egger"

  Public Overridable Property FirstName() As String
    Get
      Return Me.sFirstName
    End Get
    Set(ByVal Value As String)
      Me.sFirstName = Value
    End Set
  End Property

  Public Overridable Property LastName() As String
    Get
      Return Me.sLastName
    End Get
    Set(ByVal Value As String)
      Me.sLastName = Value
    End Set
  End Property
  Public Overridable Function GetFullName() As String
    Return Me.sLastName + ", " + Me.sFirstName
  End Function
End Class
And in C#:
public class Contact
{
  protected string sLastName = "Egger";
  protected string sFirstName = "Markus";

  public virtual string LastName
  {
   get
   {
    return this.sLastName;
   }
   set
   {
    this.sLastName = value;
   }
  }

  public virtual string FirstName
  {
   get
   {
    return this.sFirstName;
   }
   set
   {
    this.sFirstName = value;
   }
  }

  public virtual string GetFullName()
  {
   return this.sLastName + ", " + this.sFirstName;
  }
}

If you're wondering what's going on here, please read our last article. Both examples we show here are the equivalents of this VFP class:

DEFINE CLASS Contact as Custom
  LastName = "Egger"
  FirstName = "Markus"

  FUNCTION GetFullName() AS String
   RETURN this.LastName + ", " + this.FirstName
  ENDFUNC
ENDDEFINE

In VFP, you can now subclass this class and change the value of the properties in the definition, like this:

DEFINE CLASS Customer as Contact
  LastName = "Lassala"
  FirstName = "Claudio"
ENDDEFINE

In .NET, this same concept isn't valid. Fields can only have values assigned directly when they're first defined. Subsequent assignments have to occur within methods. Therefore, subclasses must assign new values in a method. A good candidate is the class' constructor, or a Configure() method the constructor calls. Here's the VB.NET version:

Public Class Customer
  Inherits Contact

  Sub New()
   Me.sFirstName = "Claudio"
   Me.sLastName = "Lassala"
  End Sub
End Class

The C# concept is identical:

public class Customer : Contact
{
  public Customer()
  {
   this.sFirstName = "Claudio";
   this.sLastName = "Lassala";
  }
}

In addition to changing field values, .NET lets you override properties (the parent class defines them as overridable and virtual respectively):

Public Class Customer
 Inherits Contact

 Public Overrides Property FirstName() As String
   Get
     Return "First Name: " + MyBase.FirstName
   End Get
   Set(ByVal Value As String)
     MyBase.FirstName = Value
   End Set
  End Property

So far, the C# version is very similar:

public class Customer : Contact
{
  public override string FirstName
  {
   get
   {
    return "First: " + base.FirstName;
   }
   set
   {
    base.FirstName = value;
   }
  }
}

There's a difference between C# and VB.NET. C# lets you specifically override the get or set part, without specifying the other. VB.NET assumes there has to be both a get and a set or else the property would be read-only or write-only, which wouldn't match the parent class' signature, and would result in a shadows situation.

In the example, you're only changing the behavior of the get method. Therefore, you could get away with this code in C#:

public class Customer : Contact
{
  public override string FirstName
  {
   get
   {
    return "First: " + base.FirstName;
   }
  }
}

This is still a read/write property, because the set-method is derived from the parent. Again, this isn't possible in VB.NET.

Conclusion

Phew! That was a lot of information on a topic that doesn't seem all that complex at first. But, there are good reasons: .NET supports practically everything VFP does as far as inheritance goes, but there's quite a bit more. In particular, the more fine-tuned control over what can be inherited is nice. Also, the ability to handle fields and properties separately is often useful, despite the fact that it makes explanations a little trickier. Constructors can be annoying when it comes to inheritance but, other than that, .NET has an awesome inheritance model. Some of the inheritance control features would certainly be nice in Visual FoxPro.

Please feel free to e-mail us with any questions.

By Claudio Lassala and Markus Egger