Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C# 2008 Step by Step.pdf
Скачиваний:
27
Добавлен:
25.03.2016
Размер:
14 Мб
Скачать
☆

172Part II Understanding the C# Language

12.Modify the first statement in the Entrance method to initialize the first variable to Month.December, as shown in bold here:

static void Entrance()

{

Month first = Month.December;

Console.WriteLine(first);

first++;

Console.WriteLine(first);

}

13.On the Debug menu, click Start Without Debugging.

Visual Studio 2008 builds and runs the program. This time the word December is written to the console, followed by the number 12. Although you can perform

arithmetic on an enumeration, if the results of the operation are outside the range of values defined for the enumerator, all the runtime can do is treat the variable as the corresponding integer value.

14.Press Enter to close the program and return to the Visual Studio 2008 programming environment.

Working with Structures

You saw in Chapter 8 that classes define reference types that are always created on the heap. In some cases, the class can contain so little data that the overhead of managing the heap becomes disproportionate. In these cases, it is better to define the type as a structure. A structure is a value type. Because structures are stored on the stack, as long as the structure is reasonably small, the memory management overhead is often reduced.

A structure can have its own fields, methods, and constructors just like a class, but not like an enumeration.

Common Structure Types

You might not have realized it, but you have already used structures in previous exercises in this book. In C#, the primitive numeric types int, long, and float are aliases for the structures System.Int32, System.Int64, and System.Single, respectively. These struc-

tures have fields and methods, and you can actually call methods on variables and literals of these types. For example, all of these structures provide a ToString method that

can convert a numeric value to its string representation. The following statements are all legal statements in C#:

int i = 99; Console.WriteLine(i.ToString()); Console.WriteLine(55.ToString()); float f = 98.765F;

Chapter 9 Creating Value Types with Enumerations and Structs

173

Console.WriteLine(f.ToString());

Console.WriteLine(98.765F.ToString());

You don’t see this use of the ToString method very often, because the Console.WriteLine method calls it automatically when it is needed. Use of the static methods exposed by

these structures is much more common. For example, in earlier chapters you used the static int.Parse method to convert a string to its corresponding integer value. What you

are actually doing is invoking the Parse method of the Int32 structure:

string s = “42”;

int i = int.Parse(s); // exactly the same as Int32.Parse

These structures also include some useful static fields. For example, Int32.MaxValue is the maximum value that an int can hold, and Int32.MinValue is the smallest value you can store in an int.

The following table shows the primitive types in C# and their equivalent types in the Microsoft .NET Framework. Notice that the string and object types are classes (reference

types) rather than structures.

Keyword

Type equivalent

Class or structure

bool

System.Boolean

Structure

 

 

 

byte

System.Byte

Structure

 

 

 

decimal

System.Decimal

Structure

 

 

 

double

System.Double

Structure

 

 

 

float

System.Single

Structure

 

 

 

int

System.Int32

Structure

 

 

 

long

System.Int64

Structure

 

 

 

object

System.Object

Class

 

 

 

sbyte

System.SByte

Structure

 

 

 

short

System.Int16

Structure

 

 

 

string

System.String

Class

 

 

 

uint

System.UInt32

Structure

 

 

 

ulong

System.UInt64

Structure

 

 

 

ushort

System.UInt16

Structure

 

 

 

174 Part II Understanding the C# Language

Declaring a Structure

To declare your own structure value type, you use the struct keyword followed by the name

of the type, followed by the body of the structure between opening and closing braces. For example, here is a structure named Time that contains three public int fields named hours, minutes, and seconds:

struct Time

{

public int hours, minutes, seconds;

}

As with classes, making the fields of a structure public is not advisable in most cases; there is no way to ensure that public fields contain valid values. For example, anyone could set the value of minutes or seconds to a value greater than 60. A better idea is to make the fields private and provide your structure with constructors and methods to initialize and manipu-

late these fields, as shown in this example:

struct Time

{

public Time(int hh, int mm, int ss)

{

hours = hh % 24; minutes = mm % 60; seconds = ss % 60;

}

public int Hours()

{

return hours;

}

...

private int hours, minutes, seconds;

}

Note By default, you cannot use many of the common operators on your own structure types. For example, you cannot use operators such as the equality operator (==) and the inequality operator (!=) on your own structure type variables. However, you can explicitly declare and implement operators for your own structure types. The syntax for doing this is covered in Chapter 21, “Operator Overloading.”

Use structures to implement simple concepts whose main feature is their value. For example, an int is a value type because its main feature is its value. If you have two int variables that contain the same value (such as 42), one is as good as the other. When you copy a value type variable, you get two copies of the value. In contrast, when you copy a reference type variable, you get two references to the same object. In summary, use structures for small

Chapter 9 Creating Value Types with Enumerations and Structs

175

data values where it’s just as or nearly as efficient to copy the value as it would be to copy an address. Use classes for more complex data so that you have the option of copying only the address of the actual value when you want to improve the efficiency of your code.

Understanding Structure and Class Differences

A structure and a class are syntactically very similar, but there are a few important differences. Let’s look at some of these differences:

You can’t declare a default constructor (a constructor with no parameters) for a structure. The following example would compile if Time were a class, but because Time is a structure, it does not:

struct Time

{

public Time() { ... } // compile-time error

...

}

The reason you can’t declare your own default constructor for a structure is that the compiler always generates one. In a class, the compiler generates the default con-

structor only if you don’t write a constructor yourself. The compiler-generated default constructor for a structure always sets the fields to 0, false, or null—just as for a class.

Therefore, you should ensure that a structure value created by the default constructor behaves logically and makes sense with these default values. If you don’t want to use these default values, you can initialize fields to different values by providing a nondefault constructor. However, if you don’t initialize a field in your nondefault structure constructor, the compiler won’t initialize it for you. This means that you must explicitly initialize all the fields in all your nondefault structure constructors or you’ll get a

compile-time error. For example, although the following example would compile and silently initialize seconds to 0 if Time were a class, because Time is a structure, it fails to

compile:

struct Time

{

public Time(int hh, int mm)

{

hours = hh; minutes = mm;

} // compile-time error: seconds not initialized

...

private int hours, minutes, seconds;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]