CHAPTER 3
Types, Objects, and Namespaces
.NET is all about objects. Not only does .NET allow you to use them, it demands that you do. Almost every ingredient you’ll use to create a web application is, on some level, really a kind of object. In this chapter, you’ll learn how objects are defined and how you manipulate them in your code. Taken together, these concepts are the basics of what’s commonly called object-oriented programming.
So, how much do you need to know about object-oriented programming to write ASP.NET web pages? It depends on whether you want to follow existing examples and cut and paste code samples or have a deeper understanding of the way .NET works and gain more control. This book assumes that if you’re willing to pick up a thousand-page book, then you’re the type of programmer who excels by understanding how and why things work the way they do. It also assumes you’re interested in some of the advanced ASP.NET programming tasks that will require class-based design, such as creating your own database component (see Chapter 22).
This chapter explains objects from the point of view of the .NET Framework. It doesn’t rehash the typical object-oriented theory, because countless excellent programming books cover the subject. Instead, you’ll see the types of objects .NET allows, how they’re constructed, and how they fit into the larger framework of namespaces and assemblies.
The Basics About Classes
When you’re starting out as a developer, classes are one of the first concepts you come across. Technically, classes are the code definitions for objects. The nice thing about a class is that you can use it to create as many objects as you need. For example, you might have a class that represents an XML file, which can be used to read some data. If you want to access multiple XML files at once, you can create several instances of your class, as shown in Figure 3-1. These instances are called objects.
Figure 3-1. Classes are used to create objects
Note At its simplest, object-oriented programming is the idea that your code should be organized into separate classes. If followed carefully, this approach leads to code that’s easier to alter, enhance, debug, and reuse.
Classes interact with each other with the help of three key ingredients:
Properties: Properties allow you to access an object’s data. Some properties are read-only, so they cannot be modified, while others can be changed. For example, the previous chapter demonstrated how you can use the read-only Length property of a String object to find out the number of letters in a string.
Methods: Methods allow you to perform an action on an object. Unlike properties, methods are used for actions that perform a distinct task or may change the object’s state significantly. For example, to open a connection to a database, you might call an Open() method in a Connection object.
Events: Events provide notification that something has happened. If you’ve ever programmed a modern Windows application, you know how controls can fire events to trigger your code. For example, if a user clicks a button, the Button object fires a Click event, which your code can react to. The same pattern works with web controls in an ASP.NET web page, although there are some limitations (as you’ll learn in Chapter 5).
In addition, classes contain their own code and internal set of private data. Classes behave like “black boxes,” which means that when you use an object, you shouldn’t waste any time wondering how it works or what low-level information it’s using. Instead, you need to worry only about the public interface of a class, which is the set of properties, methods, and events that are available for you to use. Together, these elements are called class members.
In ASP.NET, you’ll create your own custom classes to represent individual web pages. In addition, you’ll create custom classes if you design separate components. For the most part, however, you’ll be using prebuilt classes from the .NET class library, rather than programming your own.
Static Members
One of the tricks about .NET classes is that you really use them in two ways. You can use some class members without creating an object first. These are called static members, and they’re accessed by class name. For example, the DateTime type provides a static property named Now. You can access this property at any time by using the full member name DateTime.Now. You don’t need to create a DateTime object first.
On the other hand, the majority of the DateTime members require a valid instance. For example, you can’t use the AddDays() method or the Hour property without a valid object. These instance members have no meaning without a live object and some valid data to draw on.
The following code snippet uses static and instance members:
// Get the current date using a static property.
// Note that you need to use the class name DateTime.
DateTime myDate = DateTime.Now;
// Use an instance method to add a day.
// Note that you need to use the object name myDate.
myDate = myDate.AddDays(1);
// The following code makes no sense.
// It tries to use the instance method AddDays() with the class name DateTime!
myDate = DateTime.AddDays(1);
Both properties and methods can be designated as static. Static properties and methods are a major part of the .NET Framework, and you will use them frequently in this book. Some classes may consist entirely of static members (such as the Math class shown in the previous chapter), and some may use only instance members. Other classes, such as DateTime, provide a combination of the two.
The next example, which introduces a basic class, will use only instance members. This is the most common design and a good starting point.
A Simple Class
To create a class, you must define it by using a special block structure:
public class MyClass
{
// Class code goes here.
}
You can define as many classes as you need in the same file. However, good coding practices suggest that in most cases you use a single file for each class.
Classes exist in many forms. They may represent an actual thing in the real world (as they do in most programming textbooks), they may represent some programming abstraction (such as a rectangle or color structure), or they may just be a convenient way to group related functionality (as with the Math class). Deciding what a class should represent and breaking down your code into a group of interrelated classes are part of the art of programming.
Building a Basic Class
In the next example, you’ll see how to construct a .NET class piece by piece. This class will represent a product from the catalog of an e-commerce company. The Product class will store product data, and it will include the built-in functionality needed to generate a block of HTML that displays the product on a web page. When this class is complete, you’ll be able to put it to work with a sample ASP.NET test page.
After you’ve defined a class, the first step is to add some basic data. The next example defines three member variables that store information about the product—namely, its name, its price, and a URL that points to an image file:
public class Product
{
private string name;
private decimal price;
private string imageUrl;
}
A local variable exists only until the current method ends. On the other hand, a member variable (or field) is declared as part of a class. It’s available to all the methods in the class, and it lives as long as the containing object lives.
When you create a member variable, you set its accessibility. The accessibility determines whether other parts of your code will be able to read and alter this variable. For example, if ClassA contains a private variable, the code in ClassB will not be able to read or modify it. Only the code in ClassA will have that ability. On the other hand, if ObjectA has a public variable, any other object in your application is free to read and alter the information it contains. Local variables don’t support any accessibility keywords, because they can never be made available to any code beyond the current procedure. Generally, in a simple ASP.NET application, most of your variables will be private because the majority of your code will be self-contained in a single web page class. As you start creating separate components to reuse functionality, however, accessibility becomes much more important. Table 3-1 explains the access levels you can use.
Table 3-1. Accessibility Keywords
Keyword
Accessibility
public
Can be accessed by any class
private
Can be accessed only by members inside the current class
internal
Can be accessed by members in any of the classes in the current assembly (the file with the compiled code)
protected
Can be accessed by members in the current class or in any class that inherits from this class
protected internal
Can be accessed by members in the current application (as with internal)
and
by the members in any class that inherits from this class
The accessibility keywords don’t apply only to variables. They also apply to methods, properties, and events, all of which will be explored in this chapter.
Tip By convention, all the public pieces of your class (the class name, public events, properties and procedures, and so on) should use Pascal case. This means the name starts with an initial capital. (The function name DoSomething( ) is one example of Pascal case.) On the other hand, private members can use any case you want. Usually, private members will adopt camel case. This means the name starts with an initial lowercase letter. (The variable name myInformation is one example of camel case.) Some developers begin all private member names with _ or m_ (for member), although this is purely a matter of convention.
Creating an Object
When creating an object, you need to specify the new keyword. The new keyword instantiates the object, which means it grabs on to a piece of memory and creates the object there. If you declare a variable for your object but don’t use the new keyword to actually instantiate it, you’ll receive the infamous “null reference” error when you try to use your object. That’s because the object you’re attempting to use doesn’t exist, and your variable doesn’t point to anything at all.
The following code snippet creates an object based on the Product class and then releases it:
Product saleProduct = new Product();
// Optionally you could do this in two steps:
// Product saleProduct;
// saleProduct = new Product();
// Now release the object from memory.
saleProduct = null;
In .NET, you almost never need to use the last line, which releases the object. That’s because objects are automatically released when the appropriate variable goes out of scope. (Remember, a variable goes out of scope when it’s no longer accessible to your code. This happens, for example, when you define a variable in a method and the method ends. It also happens when you define a variable inside another block structure—say, a conditional if block or a loop—and that block ends.)
Objects are also released when your application ends. In an ASP.NET web page, your application is given only a few seconds to live. After the web page is rendered to HTML, the application ends, and all objects are automatically released.
Tip Just because an object is released doesn’t mean the memory it uses is immediately reclaimed. The CLR uses a long-running service (called garbage collection) that periodically scans for released objects and reclaims the memory they hold.