You're familiar with instance members in Visual FoxPro. Now find out how you can benefit from static members in Visual Studio .NET.

Properties and methods of an object aren't much of a mystery for VFP developers. In VFP, a class can have many properties and methods, which are the members of a class. Every class member defined in VFP is an instance member. Not many developers know that, so when they start learning .NET and the words instance members or static members cross their path, they get confused because it's something they've never seen in VFP.

Because VFP doesn't have anything like static members, it takes a while for VFP developers to get used to them and see their benefit. We hope this article will make it easier for you to understand this concept and start to use and appreciate this feature.

Static (or shared) and instance members

Visual FoxPro developers are familiar with instance members. Aren't you? Perhaps you just didn’t know that’s what they’re called. When a class is defined in VFP, any member (property and/or method) is an instance member. That means those members can only be used by creating instances (objects) of that class. Here's an example:

 Define Class CustomerForm as Form
DefaultCaption = "Customer's Data Preview: "
 CustomerName = ""
 Function SetFormCaption()
 This.Caption = This.DefaultCaption + This.CustomerName
 EndFunc
 EndDefine

This is a specialized class that’s designed for displaying customer data. There can be any number of instances of this class. In every instance of this class, the form's caption shows a standard caption that's defined in the class' DefaultCaption property (in this example, "Customer's Data Preview"), plus whatever value the CustomerName property has. The CustomerName property can (and probably will) have a different value for every instance of the class, assuming different customers are displayed. When the SetFormCaption method is called, it uses the "This" keyword to refer to its own data (its own instance members).

In this example, it's clear the CustomerName property is an instance member, because it belongs to the instance of the class (as mentioned, it’s going to have a separate value for every object instantiated from that class). However, in the case of the DefaultCaption property, things aren't quite as clear. Its value is defined at the class level, and it's designed to set the caption for all instances of the CustomerForm class. In other words, that value is used in every instance of the class. This means you're wasting a lot of memory because each class instance allocates space to store the string, even though the value isn't designed to change. It's simply a convenient way to define part of the caption of all customer edit forms. In this simple example, the waste of memory isn't overly significant because we’re dealing with a small string. However, there can be properties that store larger strings, or even complex objects that demand more resources from the system. The ideal scenario would be to share that property between all instances of the class. That way, the data would be stored in only one place in memory. Unfortunately, that isn't an option in VFP, but it is in .NET.

Besides supporting instance members, .NET also offers support of static (or shared) members. A static member is a member that belongs to the class (as opposed to belonging to the instances). In C#, a static member is declared using the static keyword. VB.NET uses different terminology, calling static members "shared members" (and uses a Shared keyword) because those members are shared across all instances. Other than the different terminology, there's no technical difference between both languages. To keep this article simple, we'll use the term "static" because this is the term that's used by other languages and is a standard term in the industry.

Let's see some C# code that implements the scenario proposed above. Remember, the VB.NET version's main difference would be replacing the static keyword with the Shared keyword. VB.NET also uses the keyword "Me" instead of "this":

 public class CustomerForm : System.Windows.Forms.Form
 {
 public static string DefaultCaption = "Customer's Data Preview: ";
 public string CustomerName;
 
 public void SetFormCaption()
 {
 this.Text = CustomerForm.DefaultCaption + this.CustomerName;
 }
 }

The significant parts are highlighted in bold. The DefaultCaption field is declared as static, whereas the CustomerName field is declared as an instance member. (Because it doesn't have the keyword static, it's automatically defined as an instance member.) Because the DefaultCaption field is defined as static, it only allocates a single string in memory, no matter how many instances of this class we create. All instances share this property. On the other hand, the CustomerName field gets its own value for every instance.

Now we'll focus on the SetFormCaption method. Notice that it uses "this" to refer to instance members. However, you can’t access static members using the "this" keyword because they don't belong to any specific instance of the class. Instead, they belong to the class itself. Therefore, you access them directly through the class, as was done with CustomerForm.DefaultCaption.

You can test the CustomerForm class, like this:

 CustomerForm customer1 = new CustomerForm();
 customer1.CustomerName = "EPS Software Corp.";
 customer1.SetFormCaption();
 customer1.Show();
 
 CustomerForm customer2 = new CustomerForm();
 customer2.CustomerName = "CoDe Magazine";
 customer2.SetFormCaption();
 customer2.Show();

Now suppose you have to allow the user to change the value of DefaultCaption on-the-fly. That value is presently defined inside the class and you can't let the user change the class definition. So, how can you accomplish this? All you have to do is set the CustomerForm class' DefaultCaption field before the instantiation takes place, or even later, as long as you call the SetFormCaption method again. See the bolded line in the code below:

 // Imagine you're getting a value from the user.
 CustomerForm.DefaultCaption = "The user's default: ";
 
 CustomerForm customer1 = new CustomerForm();
 customer1.CustomerName = "EPS Software Corp.";
 customer1.SetFormCaption();
 customer1.Show();
 
 CustomerForm customer2 = new CustomerForm();
 customer2.CustomerName = "CoDe Magazine";
 customer2.SetFormCaption();
 customer2.Show();

The code sets the value without instantiating the class? That's right. You don't have to instantiate the class to use its static members, because static members aren't tied to an instance.

That might sound odd to you, but if you've ever written a "Hello World!" application in .NET you probably used static members, such as MessageBox.Show() or Console.Write(), and hadn't realized it before. For example, the following code might look familiar to you:

 // Display a message to the user.
 MessageBox.Show("Hello!");
 
 // Parse a string into an integer.
 int var = Int32.Parse("50");

As you can see, you don't have to instantiate the MessageBox class to call its Show method. As you might have guessed, the Show method is a static member. The same goes for the Int32 class and its static Parse method. Think about it. It wouldn't make sense to instantiate a class just to show a message to the user or just to parse a string into an integer. In these examples, static members make a lot of sense.

There's another simple scenario that helps illustrate the use of static members. Sometimes you need to know how many instances of a form exist. In VFP, you usually do this with a form's controller object, whose main purpose might be to keep track of forms taking up memory. This approach relies on having all the opened forms added to this controller object (it usually has a collection object in it). Otherwise, it's impossible to keep track of instances. In .NET, this is relatively easy using static members. This code shows the CustomerForm class slightly altered to implement this scenario:

 public class CustomerForm : System.Windows.Forms.Form
 {
 // Static field that keeps track of
 // number of instances of this class.
 public static int InstanceCount = 0;
 
 // Default constructor.
 // It's called every time the class instantiates.
 public CustomerForm()
 {
 // Increment the counter.
 CustomerForm.InstanceCount++;
 }
 
 // This method gets called every time the form is closed.
 protected override void
 OnClosing(System.ComponentModel.CancelEventArgs e)
 {
 // Decrement counter.
 CustomerForm.InstanceCount--;
 base.OnClosing (e);
 }
 }

In this example, we added a static field called InstanceCount to the class. Its purpose is to store the number of instances of the class in memory. The field is incremented whenever a new instance of the class is created and decremented whenever the form is closed. Now you can instantiate the class as many times as you need, then query its InstanceCount field, like this:

 // Display number of instances.
 MessageBox.Show(CustomerForm.InstanceCount.ToString());
 
 CustomerForm customer1 = new CustomerForm();
 customer1.Show();
 
 CustomerForm customer2 = new CustomerForm();
 customer2.Show();
 
 // Display number of instances.
 MessageBox.Show(CustomerForm.InstanceCount.ToString());

The first dialog shows the number 0 (zero). The second one (showed after the instances were created) shows the number 2.

Static constructors

Even though you don't have to instantiate a class to access its static members, the CLR instantiates the class. That means a constructor must run when the object is created. This is where the static constructor comes in.

Whenever a class' members are accessed for the first time with code such as Class.Member, a static constructor runs. This constructor is a good place to add code for initializing static members. Referring the CustomerForm class example, imagine you have to set the DefaultCaption static field to something that can only be figured out during runtime. You can easily accomplish this using the static constructor:

 public class CustomerForm : System.Windows.Forms.Form
 {
 public static string DefaultCaption = "Customer's Data Preview: ";
 public string CustomerName;
 
 // This is the class' static constructor.
 static CustomerForm()
 {
 CustomerForm.DefaultCaption =
System.Environment.MachineName + ": ";
}
 
 public void SetFormCaption()
 {
 this.Text = CustomerForm.DefaultCaption + this.CustomerName;
 }
 }

In the static constructor, you simply assign a new value to the DefaultCaption static field (in this example, the name of the user's computer). Now you can use the class like so:

 CustomerForm customer1 = new CustomerForm();
 customer1.CustomerName = "EPS Software Corp.";
 customer1.SetFormCaption();
 customer1.Show();

The caption on the resulting form starts with the computer's name. It's important to point out that the static constructor fires whenever an object instantiates. In fact, this happens before any other constructor is invoked, even if no static member has been accessed at that point. In other words, the static constructor always fires before any other constructor, the first time a class is used after the user starts the application.

Another point to consider is there's no need to define the scope of a static method (the compiler doesn't even let you do so). This is because the static constructor always has public scope.

Also, it's important to point out that code inside the static constructor can't access instance members of the class. This is also true for static methods and properties. Again, the reason for this is that static members belong to the class. Therefore, they can't access instance members, which belong to specific instances of the class. Keep in mind there may not even be an instance of the class whenever a static member is accessed.

There are a number of scenarios in which static fields and properties are useful. One of the most typical uses is when class-specific settings don't change between instances, and those members are resource-intensive. Imagine a customer business object that has a collection of business rules. These business rules may be data driven and have to be loaded from some sort of configuration file. This is time intensive. However, all instances of the customer business object are going to use the same collection of rules. Therefore, there's no need to perform this expensive operation for each individual instance. Instead, you can implement this using static members. That means this operation only takes place once, which provides a particularly great benefit in scenarios where the application needs to scale to a large number of "hits."

Another example is a scenario in which the application couldn't possibly need more than one single member at a time. Imagine a user interface that supports Tablet PC features, such as ink recognition. You can do this using a simple InkOverlay object, which you can attach to text boxes. However, InkOverlays are heavy objects that are expensive to instantiate. However, the user can't operate more than one pen at a time, which means no more than one ink overlay can be active at any given time. This lets you make the ink overlay object a static member of a special text box class. This way, only the first text box that instantiates will incur the overhead of instantiating the ink overlay. All subsequent text boxes share that instance.

Static classes

The MessageBox class is used often by developers because its Show static method is so useful. Whoever tries to instantiate that class will get a compiler error saying "'System.Windows.Forms.MessageBox.MessageBox()' is inaccessible due to its protection level." Keep in mind that when you use the new command to instantiate a class it invokes the class' constructor, and for the constructor to be called, it has to be accessible (public). The above error message is a result of the MessageBox's class not having a public constructor. Instead, the constructor is set to be private, effectively keeping the class from ever being instantiated (at least from outside the class).

Instantiating the MessageBox class doesn't make sense given the fact that all we're interested in is the class' Show method, which is static, and therefore doesn't require the class to instantiate in order to be used. To prevent a class from being instantiated from the outside, don't create a public constructor for the class. A class that has static methods and no public constructor is normally referred to as a static class. Think of a static class as an advanced collection of functions and variables assigned to an object. These functions can take advantage of many object-oriented features and are therefore more powerful than regular function libraries, but they aren't quite true objects.

We'll build an example of such a class. As a VFP developer, you're used to using the Sys function and its parameters which you can pass to get all sorts of different functionality. The following example creates a wrapper for three of those functionalities so you can use them in .NET (it's worth pointing out again that the main difference in VB is syntax and the use of the "shared" keyword instead of "static." The concept remains the same though.)

 // An example of a static class.
 public class Sys
 {
 // Class constructor declared as private,
 // preventing class from instantiating.
 private Sys()
 {
 }
 
 // Mimics Sys(2023) - returns Temporary Path
 public static string TemporaryPath()
 {
 return System.IO.Path.GetTempPath();
 }
 
 // Mimics Sys(0) - Network Machine Information
 public static string NetworkMachineInformation()
 {
 return System.Environment.MachineName +
" # " + System.Environment.UserName;
}
 
 // Mimics Sys(3) - Legal File Name
 public static string LegalFileName()
 {
 Random rnd = new Random();
 // we want an 8-digit string.
 return rnd.Next(99999999).ToString();
 }
 }

You can use the Sys class without instantiating it (the compiler will complain about any attempt of instantiation), like this:

 MessageBox.Show(Sys.LegalFileName());
 MessageBox.Show(Sys.NetworkMachineInformation());
 MessageBox.Show(Sys.TemporaryPath());

I must confess I like that better than the cryptic Sys(2023), Sys(0), and Sys(3).

A small note about the way VB.NET works. Besides supporting the way C# works, fully-qualifying things such as Sys.LegalFileName(), it's also possible to import the whole class like a namespace, then use the methods directly:

 ' Imports the class like a namespace
 Imports Example.Sys
 
 ' Call the method directly
 MsgBox.Show(LegalFileName())

Static classes are also a good way to create helper classes. In VFP, developers create a lot of procedural helper functions, spreading them throughout .PRG files. A better way to accomplish that is by grouping related functions together, turning them into methods within a class. In VFP, this sort of class isn't worth the trouble of instantiation (nor the memory requirements that go along with that). The .NET approach to creating static classes is a better solution because you can use the "functions" in an objectified way (as opposed to a procedural way, and therefore, benefit from OOP features, such as encapsulation, abstraction, and inheritance), without actually creating objects for it.

Singleton objects

Occasionally, you have to control the number of times a class instantiates. More commonly, there are classes that should only instantiate a maximum of one time. An object that's meant to exist only once in memory is called a Singleton object.

As an example, consider an application object (in VFP this object is called oApp), whose primary purpose is to be the main object in the application, and it's responsible for setting up helper objects, controller (or manager) objects, etc. A running application shouldn't have more than one instance of this class, but there's no easy way to enforce this in VFP. This is easily accomplished in .NET using a mix of private constructors and static members, as shown below:

 // A Singleton class example.
 public class App
 {
 // Private constructor.
 private App()
 {
 }
 
 // An instance member.
 // Keeps the name of the application.
 public string ApplicationName;
 
 // Static read-only field that keeps an instance of this class.
 public static readonly App Instance = new App();
 
 }

The class looks simple, doesn't it? In fact, it is. The private constructor prevents the class from instantiating. The ApplicationName public field is simply an example member to demonstrate that this class could have properties, fields, and methods. In a real-world scenario, this class would have a number of members.

Finally, there's the Instance field. This field is marked as public to make it accessible outside the class. It's also marked as static so you can access it without instantiating the class. Then, it's marked as read-only, which means it can't have anything assigned to it. Finally, a new instance of this class instantiates and is assigned to this field. This last part might sound confusing, so we'll explain it. Remember, the class doesn't have a public constructor so it can't be instantiated from outside. However, it can be instantiated from within itself. And because this is the field definition, something can be assigned to it as its initial value. After this, the read-only effect kicks in.

To make sure this magic works, you can test the class like this:

 // Get a reference to the App object.
 App oApp1 = App.Instance;
 
 // Assign a value to the instance field.
 oApp1.ApplicationName = "My First App";
 
 // Now store the reference to a second variable.
 App oApp2 = App.Instance;
 
 // And assign a different value.
 oApp2.ApplicationName = "My Second App";
 
 // Display the instance field of both variables.
 MessageBox.Show(oApp1.ApplicationName + "\r\n" +
 oApp2.ApplicationName);

Notice we didn't instantiate the App class directly. You can obtain a reference to an instance of it by accessing App.Instance. oApp1 is an object in memory; therefore, all its public instance members are available to other objects. oApp2 receives a reference to the App object and a different value is assigned to the instance member (the ApplicationName field). When we show that field from both variables (oApp1 and oApp2), they show the same value. This demonstrates there's only a single instance of that class sitting in memory.

This is what such a class would look like in VB.NET:

 Public Class App
 
 Public ApplicationName As String
 
 Public Shared ReadOnly Instance As New App
 
 Private Sub New()
 End Sub
 
 End Class

This is a simple example of a Singleton object and how to implement it. Depending on how a .NET application is architected, you'll typically choose to have an application static class instead of a singleton object. However, there are many other scenarios in which singleton classes are useful. For example, there can only be a single file system object, a single user object, etc.

Conclusion

In this part of our series we went over the differences between VFP and .NET in the context of static and instance members. You saw that VFP only has instance members, whereas .NET has both. VFP developers coding in .NET might miss things such as procedural functions that don't require objects to be used, and global variables which can be accessed throughout the application. In a way, .NET's static members give you what procedural functions and global variables give to VFP, but they give you more than that because you can also benefit from OOP features.

By Claudio Lassala and Markus Egger