Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

CSharp Bible (2002) [eng]-1

.pdf
Скачиваний:
42
Добавлен:
16.08.2013
Размер:
4.29 Mб
Скачать

Accessing the individual members of the structure is as easy as writing the name of the structure variable identifier, a period, and then the structure member. Listing 7-1 shows how a structure may be used in code.

Listing 7-1: Accessing Structure Members

class Listing7_1

{

struct Point

{

public int X; public int Y;

}

public static void Main()

{

Point MyPoint;

MyPoint.X = 100;

MyPoint.Y = 200; System.Console.WriteLine(MyPoint.X); System.Console.WriteLine(MyPoint.Y);

}

}

The output for the example show would be as follows:

100

200

You can assign one structure variable to another, as long as the structures are of the same type. When you assign one structure variable to another, C# sets the values of the structure variable shown before the equal sign to the values of the corresponding values found in the structure shown after the equal sign, as shown in Listing 7-2.

Listing 7-2: Assigning One Structure Variable to Another

class Listing7_2

{

struct Point

{

public int X; public int Y;

}

public static void Main()

{

Point MyFirstPoint; Point MySecondPoint;

MyFirstPoint.X = 100;

MyFirstPoint.Y = 100;

MySecondPoint.X = 200;

MySecondPoint.Y = 200;

System.Console.WriteLine(MyFirstPoint.X);

System.Console.WriteLine(MyFirstPoint.Y);

MyFirstPoint = MySecondPoint;

System.Console.WriteLine(MyFirstPoint.X);

System.Console.WriteLine(MyFirstPoint.Y);

}

}

The preceding code sets the MyFirstPoint members to 100 and the MySecondPoint members to 200. The MyFirstPoint values are written to the console, and then the values in the MyFirstPoint variable is copied into the values found in the MySecondPoint variable. After the assignment, the MyFirstPoint values are again written to the console. When this code is compiled and executed, the output should be that of Figure 7-1.

Figure 7-1: Assigning one structure to another

Any values in a structure are overwritten in an assignment with the values from the structure variable listed after the equal sign.

Defining Methods in Structures

You can include methods in structures as well as variables. If you need to write code that works with the contents of a structure, you might consider writing the method inside of the structure itself.

Using constructor methods

A structure may include a special method called a constructor. A constructor method executes when a variable declaration using the structure type is executed at runtime.

Structures may have zero or more constructors. Structure constructor declarations are much like class method declarations, with the following exceptions:

Constructors do not return any values. Do not use a return type keyword when writing a structure constructor — not even void.

Constructor identifiers have the same name as the structure itself.

Constructors must have at least one parameter. C# does not allow you to define a constructor with no parameters. C# always defines a default constructor with no

parameters for you. This is the constructor that initializes all of the structure members to zero, or their equivalent.

A structure may define more than one constructor, as long as the constructors have different parameter lists. Listing 7-3 shows a Point structure with two constructors.

Listing 7-3: Structure Constructors

class Listing7_3

{

struct Point

{

public int X; public int Y;

public Point(int InitialX)

{

X = InitialX; Y = 1000;

}

public Point(int InitialX, int InitialY)

{

X = InitialX;

Y = InitialY;

}

}

public static void Main()

{

Point MyFirstPoint = new Point(); Point MySecondPoint = new Point(100);

Point MyThirdPoint = new Point(250, 475);

System.Console.WriteLine(MyFirstPoint.X);

System.Console.WriteLine(MyFirstPoint.Y);

System.Console.WriteLine(MySecondPoint.X);

System.Console.WriteLine(MySecondPoint.Y);

System.Console.WriteLine(MyThirdPoint.X);

System.Console.WriteLine(MyThirdPoint.Y);

}

}

Figure 7-2 shows what appears on the console if you compile and run the code in Listing 7-3.

Figure 7-2: The structures reveal predefined values as expected.

Note several interesting concepts in Listing 7-3:

The Point structure declares two constructors. One takes a single integer as an argument and the other takes two integers as an argument. Both are prefixed with the keyword public so that their code is publicly accessible to the rest of the code in the class.

The constructor with one integer parameter sets the structure's X member to the value of the integer argument, and sets the structure's Y member to 1,000.

The constructor with two integer parameters sets the structure's X member to the value of the first integer argument, and sets the structure's Y member to the value of the second integer argument.

The code declares three variables of type Point. They each call one of the Point constructors. The declaration of MyFirstPoint calls the constructor with zero arguments. This is the default constructor that C# defines for every structure. The declaration of MySecondPoint calls the constructor with one argument, and the declaration of MyThirdPoint calls the constructor with two arguments.

Pay close attention to the syntax in Listing 7-3 that invokes a structure constructor. If you want to invoke a constructor on a structure, you must use the new keyword, followed by the name of the structure, followed by the constructor parameters in parentheses. The value of that expression is assigned to the variable you are declaring. Take a look at the following statement:

Point MyThirdPoint = new Point(250, 475);

This statement says: "Create a new Point structure using the constructor with two integers. Assign its value to the MyThirdPoint variable. Because of the rules of structure assignment previously described, the MyThirdPoint variable has its members set to the values of the members of the new structure. You do not need to do anything else with the new structure created when new was called. The Common Language Runtime (CLR) detects that the structure is no longer in use and disposes of it through its garbage collection mechanism.

The parameterless constructor syntax is also shown in Listing 7-3:

Point MyFirstPoint = new Point();

This tells the C# compiler that you want to initialize the structure using its default behavior. You must assign values to all of the members of a structure before you use a structure, either

by invoking its parameterless constructor or by explicitly setting all of its fields to a value. Take a look at Listing 7-4.

Listing 7-4: Using a Structure Before Initialization Results in Compiler Errors

class Listing7_4

{

struct Point

{

public int X; public int Y;

}

public static void Main()

{

Point MyPoint;

System.Console.WriteLine(MyPoint.X);

System.Console.WriteLine(MyPoint.Y);

}

}

The preceding code is in error, and compiling it produces the following error messages from the C# compiler:

error CS0170: Use of possibly unassigned field 'X' error CS0170: Use of possibly unassigned field 'Y'

warning CS0649: Field 'Listing7_4.Point.X' is never assigned to, and will always have its default value 0

warning CS0649: Field 'Listing7_4.Point.Y' is never assigned to, and will always have its default value 0

The error messages are telling you that the calls to WriteLine() use data members in the structure, but that those data members have not yet been given a value. The MyPoint variable has not been initialized with a call to a parameterless constructor, nor have its members been explicitly set to any values. C# does not invoke the parameterless constructor unless you write the call in your code.

This is another example of the C# compiler protecting your code from unpredictable behavior. All variables must be initialized before they are used.

Calling methods from structures

You may also write methods in your structures. These methods follow the same rules as class methods: They must specify a return type (or void), and have an identifier and an argument list, which may be empty. Calling a method in a structure uses the same dot notation syntax that is used when you access a class method. Take a look at Listing 7-5.

Listing 7-5: Calling Structure Methods

class Listing7_5

{

struct Point

{

public int X; public int Y;

public Point(int InitialX, int InitialY)

{

X = InitialX;

Y = InitialY;

}

public bool IsAtOrigin()

{

if((X == 0) && (Y == 0)) return true;

else

return false;

}

}

public static void Main()

{

Point MyFirstPoint = new Point(100, 200); Point MySecondPoint = new Point();

if(MyFirstPoint.IsAtOrigin() == true) System.Console.WriteLine("MyFirstPoint is at the origin.");

else

System.Console.WriteLine("MyFirstPoint is not at the origin.");

if(MySecondPoint.IsAtOrigin() == true) System.Console.WriteLine("MySecondPoint is at the origin.");

else

System.Console.WriteLine("MySecondPoint is not at the

origin.");

}

}

The Point structure in Listing 7-5 declares a method called IsAtOrigin. The code in that method checks the values of the structure methods, returning true if the coordinates of the point are (0, 0) and false otherwise.

The Main() method declares two variables of type Point: the MyFirstPoint variable is set to coordinates of (100, 200) using the explicit constructor, and the MySecondPoint variable is set to coordinates of (0, 0) using the default parameterless constructor. The Main() method then calls the IsAtOrigin method on both points and prints out a message based on the method's return value.

If you compile and run the code in Listing 7-5, you see the following output on the console:

MyFirstPoint is not at the origin.

MySecondPoint is at the origin.

Be sure to prefix your methods with the keyword public if you want them to be publicly accessible to the rest of the code in the class.

Defining Properties in Structures

Properties within a structure enable you to read, write, and compute values with the use of accessors. Unlike fields, properties are not considered variables; therefore, they do not designate storage space. Because a property does not allocate storage space, it cannot be passed as a ref or out parameter.

Cross-Reference Properties is discussed in detail in Chapter 9., "C# Classes."

Listing 7-6 includes a property within the Point structure.

Listing 7-6: Defining a Property Within a Structure

class Listing7_6

{

struct Point

{

private int x; public int X

{

get

{

return x;

}

set

{

x = value;

}

}

}

public static void Main()

{

int RetValue;

Point MyPoint = new Point();

MyPoint.X = 10; RetValue = MyPoint.X;

System.Console.WriteLine(RetValue);

}

}

This code assigns a value to the X member of the Point structure and then retrieves this value into the RetValue variable. The output from Listing 7-6 is shown in Figure 7-3.

Figure 7-3: Defining a property within a structure

Using properties is an excellent means to read, write, and calculate data within a structure. You don't need to include bulky methods that perform the calculations for you, and you can define how and when the get and set accessors are allowed to operate.

Defining Indexers in Structures

Indexers are objects that enable a structure to be indexed in very much the same way that arrays do. With an indexer, you can declare several structures at the same time and refer to each structure using an index number. This is demonstrated in Listing 7-7, which declares a structure called MyStruct containing a string and an index.

Listing 7-7: Including an Indexer Within a Structure

class Listing7_7

{

struct MyStruct

{

public string []data ;

public string this [int index]

{

get

{

return data[index];

}

set

{

data[index] = value;

}

}

}

public static void Main()

{

int x;

MyStruct ms = new MyStruct(); ms.data = new string[5]; ms[0] = "Brian D Patterson"; ms[1] = "Aimee J Patterson"; ms[2] = "Breanna C Mounts"; ms[3] = "Haileigh E Mounts"; ms[4] = "Brian W Patterson"; for (x=0;x<5;x++)

System.Console.WriteLine(ms[x]);

}

}

As you can see, this example has created a new MyStruct object and then set its data member to 5, indicating that five copies of this structure are used. You reference each copy of this structure using an index number (0 through 5) and store names within this structure. To ensure that all of your data remains intact, you do a simple loop through the possible index numbers and write the output to the console.

You can see the output for Listing 7-7 in Figure 7-4.

Figure 7-4: Include an indexer within a structure for easy retrieval of data.

An indexer within a structure can come in very handy when you are dealing with large amounts of the same data. For example, if you were to read in address information from a database, this would be an excellent place to store it. You maintain all the fields while providing a mechanism to easily access each piece of data within the records.

Defining Interfaces in Structures

Interfaces are a way of ensuring that someone using your class has abided by all the rules you set forth to do so. This can include implementing certain methods, properties, and events. When you expose an interface, users of your interface must inherit that interface; and in doing so, they are bound to create certain methods and so forth. This ensures that your class and/or structure is used as it was intended.

You can include an interface within a structure as well. Listing 7-8 shows you how to properly implement an interface.

Listing 7-8: Implementing an Interface Within a Structure

class Listing7_8

{

interface IInterface

{

void Method();

}

struct MyStruct : IInterface

{

public void Method()

{

System.Console.WriteLine("Structure Method");

}

}

public static void Main()

{

MyStruct DemoStructure = new MyStruct(); DemoStructure.Method();

}

}

This code creates an interface called IInterface. This interface contains the definition for one method called Method. You create your structure and end the structure name with a colon followed by the name of the interface from which you wish to inherit. Within your structure, you include the method, which simply writes a line of text out to the console. You can see the output for this program in Figure 7-5.

Figure 7-5: Implementing an interface within a structure

To demonstrate how important the interface is, comment out the four lines that make up the Method method within the MyStruct structure. Now recompile the program, and you should see the following error message:

Class1.cs(8,9): error CS0535: 'Listing7_8.MyStruct' does not implement interface member 'Listing7_8.IInterface.Method()'

The C# compiler determined that you did not implement all the methods set forth by the interface. Because the correct method was not implemented, the program could not be compiled, thereby ensuring that you follow all the rules.

Using C# Simple Types as Structures

The primitive types described in Chapter 3 — int, uint, long, and the like — are actually implemented as structures in the .NET CLR. Table 7-1 lists the C# value variable keywords and the names of the .NET structures that actually implement them.

 

Table 7-1: .NET Structure Names for Value Types

 

 

 

 

C# Keyword

 

 

.NET Structure Name

 

 

 

 

sbyte

 

 

System.SByte

 

 

 

 

Соседние файлы в предмете Программирование на C++