Defining
Classes
Classes
are the most fundamental of C#’s types. A class is a data structure that
combines state (fields) and actions (methods and other function members) in a
single unit. A class provides a definition for dynamically created instances of the class, also known as objects.
Classes support inheritance and polymorphism,
mechanisms whereby derived classes can extend and
specialize base classes.
New classes are created
using class declarations. A class declaration starts with a header that
specifies the attributes and modifiers of the class, the name of the class, the
base class (if any), and the interfaces implemented by the class. The header is
followed by the class body, which consists of a list of member declarations
written between the delimiters {
and }.
The syntax used for defining classes
in C# is simple, especially if you usually program in C++ or Java:
[attributes] [modifiers] class <className> [: baseClassName]
{
[class-body]
}[;]
let’s look at a simple class declaration to
get started:
class Employee
{
private long employeeId;
}
As you can see, this class is as
basic as it gets. We have a class named Employee that contains a single member
named employeeId. Notice private, which precedes our member. This is called an access
modifier.
If you come from a C++ background,
note that it’s not necessary to place a terminating semicolon at the end of a
class. However, you can do so if you want; in fact, I do this in some of my
classes simply out of habit. Having said that, the following two class
declarations are identical:
class MyClass
{
// Members
}
class MyClass
{
// Members
};
Now let’s look at the various types
of members that can be defined with a class.
Class
Members
Put simply, classes consist of
members. Everything you define within a class is considered to be a member of
that class. You already know from Chapter 2, “The .NET Type System,” that all
the types available to C# programmers originate from the common type system
(CTS). Here’s a list of the various types that you can define as members of a
C# class:
- Fields
A field is
a member variable used to hold a value. You can apply several modifiers to a
field, depending on how you want the field used. These modifiers include
static, readonly, and const. We’ll discuss what these modifiers signify and how
to use them shortly.
- Methods
A method
is the actual code that acts on the object’s data (or field values).
- Properties
Properties
are sometimes called smart fields because they’re actually methods that look
like fields to the class’s clients. This allows the client a greater degree of
abstraction because it doesn’t have to know whether it’s accessing the field
directly or whether an accessor method is being called.
- Constants
As the
name suggests, a constant is a field with a value that can’t be changed .
- Indexers
Just as a
property is a smart field, an indexer is sometimes referred to as a smart
array—that is, a member that enables you to work with a class that’s logically
an array of data, as though the class itself were an array. For example,
although a ListBox class might have other fields (such as a sort bit) and
methods to manipulate and present the control’s data, this class will be
conceptually defined by the array of data elements that it’s displaying.
However, to index the class’s data, the class designer typically either allows
direct access to the class’s internal data array or provides a method that
takes a subscript, or index, value to define which array element is being dealt
with. Indexers, enable you to subscript
the actual object, thereby giving the client a much more intuitive means of
using the class.
- Events
An event
causes some piece of code to run. Events are an integral part of Microsoft
Windows programming. For example, an event is fired when a user moves the mouse
or clicks or resizes a window. C# events use the standard publish/subscribe
design pattern seen in Microsoft Message Queuing (MSMQ) and the COM+
asynchronous event model, which gives an application asynchronous event-handling
capabilities. But in C#, this design pattern is a “first-class” concept—meaning
that the language was designed with this in mind instead of being bolted on
after the fact.
- Operators
C# gives
you the ability, via operator overloading, to add the standard mathematical
operators to a class so that you can write more intuitive code.
Access
Modifiers
Now that you’ve briefly read about
the different types that can be defined as members of a C# class, let’s look at
some important modifiers used to specify how visible, or accessible, a given
member is to code outside its own class. These modifiers, called access
modifiers, are listed along with their descriptions in the following table
C# Access Modifiers
|
|
Access Modifier
|
Description
|
Public
|
Signifies that the member is
accessible from outside the class’s definition and hierarchy of derived
classes.
|
Protected
|
The member isn’t visible outside
the class and can be accessed by derived classes only.
|
Private
|
The member can’t be accessed
outside the scope of the defining class. Therefore, not even derived classes
have access to these members.
|
Internal
|
The member is visible only within
the current compilation unit. The internal access modifier creates a hybrid
of public and protected accessibility, depending on where the code resides.
|
Note that unless you want a member
to have the default access modifier of private, you must specify an access
modifier for it. This is in contrast to C++, in which a member that’s not
explicitly decorated with an access modifier assumes the visibility
characteristics of the previously stated access modifier. For example, in the
following C++ code, the members a, b, and c are defined with public visibility,
and the members d and e are defined as protected members:
class CAccessModsInCpp
{
public:
int a;
int b;
int c;
protected:
int d;
int e;
};
To accomplish the same goal in C#,
you would have to change this code to the following:
class AccessModsInCSharp
{
public int a;
public int b;
public int c;
protected int d;
protected int e;
}
The following C# code results in the
member b being declared as private because no access modifier was specified for
that member:
public MoreAccessModsInCSharp
{
public int a;
int b;
}
The
Main Method
Every C# application must define a
method named Main in one of its classes. This method, which serves as that
application’s entry point, must be defined as static. (We’ll discuss what
static means shortly.) It doesn’t matter to the C# compiler which class has the
Main method defined, and the class you choose doesn’t affect the order of
compilation. This is unlike C++, in which you must monitor dependencies closely
when building an application. The C# compiler is smart enough to go through
your source files and locate the Main method on its own. However, this
all-important method is the entry point to all C# applications.
Although you can place the Main
method in any class, I recommend creating a class specifically for housing this
method. Here’s an example of doing that using our—so far—simple Employee class:
class Employee
{
private int employeeId;
}
class AppClass
{
static public void Main()
{
Employee emp = new Employee();
}
}
As you can see, the example has two
classes. This is a common approach to C# programming even in the simplest
applications. The first class (Employee) is a problem domain class, and the
second class (AppClass) contains the needed entry point (Main) for the
application. In this case, the Main method instantiates the Employee object. If
this were a real application, the Main method would use the Employee object’s
members.
Command-Line
Arguments
You can access the command-line
arguments to an application by declaring the Main method as taking a string array
type as its only argument. Then you can process the arguments as you would any
array.Here’s some generic code for iterating through the command-line arguments
of an application and writing them to the standard output device:
using System;
class CommandLine
{
public static void Main(string[] args)
{
Console.WriteLine("\nYou specified {0} arguments",
args.Length);
foreach (string arg in args)
{
Console.WriteLine("Argument: {0}", arg);
}
}
}
Figure….. shows an example of
calling this application with a couple of randomly selected values.
Returning
Values from Main
Most examples in this book define
Main as follows:
class SomeClass
{
// Other members
public static void Main()
{
// Main body
}
}
However, you can also define Main to
return a value of type int. Although not common in GUI applications, this
return value can be useful when you’re writing console applications to be run
in batch. The return statement terminates execution of the method, and the
returned value is used as an error level to the calling application or batch
file to indicate user-defined success or failure. To do this, use the following
prototype:
public static int Main()
{
// Return some value of type int
// that represents success or value.
return 0;
}
Multiple
Main Methods
The designers of C# included a
mechanism by which you can define more than one class with a Main method. Why
would you want to do this? One reason is to place test code in your classes.
You can then use the /main:<className> switch with the C# compiler to
specify which class’s Main method to use. Here’s an example that has two
classes containing Main methods:
using System;
class Main1
{
public static void Main()
{
Console.WriteLine("Main1");
}
}
class Main2
{
public static void Main()
{
Console.WriteLine("Main2");
}
}
To compile this application so that
the Main1.Main method is used as the application’s entry point, you’d use this
switch:
csc MultipleMain.cs /main:Main1
No comments:
Post a Comment