Flylib.com

Books Software

 
 
 

Struct Functions


Struct Functions

In the last chapter you looked at struct types for storing multiple data elements in one place. Structs are actually capable of a lot more than this. One important extra capability they offer is the ability to contain functions as well as data. This is something that may seem a little strange at first, but it is in fact very useful indeed.

As a simple example, consider the following struct:


struct customerName


{


public string firstName, lastName;


}

If you have variables of type customerName, and you want to output a full name to the console, you are forced to build the name from its component parts . You might use the following syntax for a customerName variable called myCustomer , for example:


customerName myCustomer;


myCustomer.firstName = "John";


myCustomer.lastName = "Franklin";


Console.WriteLine("{0} {1}", myCustomer.firstName, myCustomer.lastName);

By adding functions to structs, you can simplify this by centralizing the processing of common tasks such as this. You can add a suitable function to the struct type as follows :

struct customerName { public string firstName, lastName;

public string Name ()


{


return firstName + " " + lastName;


}

}

This looks much like any other function you've looked at in this chapter, except that you haven't used the static modifier. The reasons for this will become clear later in the book, for now it is enough to know that this keyword isn't required for struct functions. You can use this function as follows:

customerName myCustomer; myCustomer.firstName = "John"; myCustomer.lastName = "Franklin";

Console.WriteLine(myCustomer.Name());

This syntax is much simpler, and much easier to understand, than the earlier one.

An important point to note here is that the Name() function has direct access to the firstName and lastName struct members . Within the customerName struct, they can be thought of as global.



Overloading Functions

Earlier in this chapter, you saw how you must match the signature of a function when you call it. This implied that you would need to have separate functions to operate on different types of variable. Function overloading provides you with the ability to create multiple functions with the same name , but each working with different parameter types.

For example, earlier you used the following code, which contained a function called MaxValue() :

class Program { static int MaxValue(int[] intArray) { int maxVal = intArray[0]; for (int i = 1; i < intArray.Length; i++) { if (intArray[i] > maxVal) maxVal = intArray[i]; } return maxVal; } static void Main(string[] args) { int[] myArray = {1, 8, 3, 6, 2, 5, 9, 3, 0, 2}; int maxVal = MaxValue(myArray); Console.WriteLine("The maximum value in myArray is {0}", maxVal); Console.ReadKey(); } }

This function can only be used with arrays of int values. Now, you could provide different named functions for different parameter types, perhaps renaming the above function as IntArrayMaxValue() and adding functions such as DoubleArrayMaxValue() to work with other types. Alternatively, you could just add the following function to your code:

...

static double MaxValue(double[] doubleArray)


{


double maxVal = doubleArray[0];


for (int i = 1; i < doubleArray.Length; i++)


{


if (doubleArray[i] > maxVal)


maxVal = doubleArray[i];


}


return maxVal;


}

...

The difference here is that you are using double values. The function name, MaxValue() , is the same, but (crucially) its signature is different. It would be an error to define two functions with the same name and signature, but since these two functions have different signatures, this is fine.

Now, you have two versions of MaxValue() , which accept int and double arrays, and return an int or double maximum, respectively.

The beauty of this type of code is that you don't have to explicitly specify which of these two functions you wish to use. You simply provide an array parameter, and the correct function will be executed depending on the type of the parameter used.

{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}

At this point, it is worth noting another feature of the IntelliSense feature in VS. If you have the two functions shown above in an application and then proceed to type the name of the function in (for example) Main() , VS will show you the available overloads for the function. If you type the following:


double result = MaxValue(

VS gives you information about both versions of MaxValue() , which you can scroll between using the up and down arrow keys, as shown in Figure 6-9.

image from book
Figure 6-9

All aspects of the function signature are included when overloading functions. You might, for example, have two different functions that take parameters by value and by reference, respectively:


static void ShowDouble(ref int val)

{ ... }

static void ShowDouble(int val)

{ ... }

The choice as to which of these versions to use is based purely on whether the function call contains the ref keyword. The following would call the reference version


ShowDouble(ref val);

and the following would call the value version:


ShowDouble(val);

Alternatively, you could have functions that differ in the number of parameters they require, and so on.