BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

C# Programming
.NET 1.1+

C# Structures

The twenty-second, and final, part of the C# Object-Oriented Programming tutorial reviews the use of structures. Structures provide similar functionality to classes, but when instantiated resultant variables are value types, rather than reference types.

What is a Structure?

A structure is similar in functionality and syntax to a class. Structures are composite data types, containing properties, methods and other members, that can be instantiated as a variable. The key difference between structures and classes is that, whereas classes are used to generate reference type variables, instances of structures are always value types.

Structure Members

In addition to properties and methods, structures can contain many other public and private members. These include:

  • Constructors. Multiple constructors can be created within a structure. However, a default constructor, containing no parameters, may not be defined. The default constructor is implicit for all structures and cannot be overridden. It simply sets all of the fields in the structure to their default values.
  • Constants. Both constants and enumerations may be defined within a structure.
  • Fields. Fields are variables defined within the code block of a structure that are available to all of its members. Fields can be declared as either public or private though public fields are discouraged as they limit encapsulation. Unlike fields within classes, structure fields may not be initialised in their declaration code. If initialisation is required, this must be performed within a constructor.
  • Indexers. A structure can include an indexer to provide array-like functionality.
  • Operators. To permit structures to behave like native data types, it is possible to overload their operators. This permits operators such as + and - to be used with instances of a structure.
  • Events. Structures can include declarations for events, permitting a structure to raise notifications of actions taken or states reached. Care must be taken when using events within structures. As structures are value types, it is possible to subscribe to an event within a copy of a structure instance that later goes out of scope. This can lead to a raised event unexpectedly not being captured.

Further Limitations

In addition to the above limitations of structures when compared to classes, there are some further restrictions. The most important of these is that structures do not support inheritance. It is not possible for one structure to inherit functionality from another structure or class; neither can structures be used as the base for inheritance. Members may not, therefore, be declared as protected, abstract or virtual as this would be meaningless. The only exception to this rule is that structures do inherit from object, as do all other types.

The lack of inheritance is offset somewhat as structures may implement one or more interfaces. This permits a degree of polymorphism.

Another limitation of structures is that they may not include a destructor. A destructor is unnecessary because the compiler destroys instances of structures automatically.

When to use Structures

You may be asking why you would use structures, given that they are more restrictive that classes. The answer is that, in some circumstances, structures can be more efficient than classes and can lead to improved performance and resource utilisation. These tend to be situations where the structures are simple, containing few properties, and are used in large numbers.

A lightweight class is disadvantaged in comparison to a similar structure in two ways. Firstly, more memory is used by a single class instance because both the data and the reference to that data must be stored. A structure variable does not need to store the additional reference information so has a smaller memory "footprint". Secondly, all access to a structure's properties can be made directly. With an object based upon a class, the access is indirect, using the reference first. Each of these drawbacks is minor for individual variable uses. However, when performing many thousands or millions of operations, the cumulative effect can be significant.

The performance gain and smaller resource usage of structures is limited to those that are lightweight. As the complexity of a structure grows, the relative improvements when compared to using a class are minimised. When a structure contains many properties or several constructors, events, indexers or operators, it is often more appropriate to use a class.

Creating a Structure

To demonstrate the use of structures, we will create one that represents a vector. This simple structure will include X and Y properties and a method that calculates the length of the vector. To begin, create a new console application named "CSharpStructures" and add a new class file named "Vector" to the project.

Syntax

The syntax for declaring a structure is similar to that of a class. However, instead of using the class keyword, the structure name is prefixed with "struct". The general syntax for a simple structure is therefore:

struct structure-name {}

As described above, structures may implement one or more interfaces. If required, the interface names are appended to the declaration as a comma-separated list. The first interface's name is prefixed with a colon character (:).

struct structure-name : interface-1, interface-2, ..., interface-x {}

Depending upon the development environment that you prefer, the generated Vector code file may include a class definition. If it does, remove it. Add the new structure definition to the code file as follows:

struct Vector
{
}
5 May 2008