So far, you have seen how classes offer a great way of encapsulating objects in your program. You have also seen how they are stored on the heap in a way that gives you much more flexibility in data lifetime, but with a
class Dimensions { public double Length; public double Width; }
This code defines a class called
Dimensions
, which simply stores the length and width of some item. Perhaps you’re writing a furniture-arranging program to let people experiment with rearranging their furniture on the computer, and you want to store the dimensions of each item of furniture. It looks like you’re breaking the rules of good program design by making the fields public, but the point is that you don’t really need all the facilities of a class for this at all. All you have is two
As mentioned earlier in this chapter, the only thing you need to change in the code to define a type as a struct instead of a class is to replace the keyword class with struct :
struct Dimensions { public double Length; public double Width; }
Defining functions for structs is also exactly the same as defining them for classes. The following code
struct Dimensions { public double Length; public double Width; Dimensions(double length, double width) { Length=length; Width=width; } public double Diagonal { get { return Math.Sqrt(Length*Length + Width*Width); } } }
In many ways, you can think of structs in C# as being like scaled-down classes. They are basically the same as classes but designed more for cases where you simply want to
Structs are value types, not reference types. This means they are stored either in the stack or inline (if they are part of another object that is stored on the heap) and have the same lifetime restrictions as the simple data types.
Structs do not support inheritance.
There are some differences in the way constructors work for structs. In particular, the compiler always
With a struct, you can specify how the fields are to be laid out in memory (this is examined in Chapter 12, “Reflection,” which covers attributes).
Because structs are really intended to group data items together, you’ll sometimes find that most or all of their fields are declared as public. This is,
| Tip |
C++ developers beware; structs in C# are very different from classes in their implementation. This is very different than the situation in C++, for which classes and structs are virtually the same thing. |
The following sections look at some of these differences in more detail.
Although structs are value types, you can often treat them syntactically in the same way as classes. For example, with the definition of the Dimensions class in the previous section, you could write:
Dimensions point = new Dimensions(); point.Length = 3; point.Width = 6;
Note that because structs are value types, the
new
operator does not work in the same way as it does for classes and other reference types. Instead of allocating memory on the heap, the
new
operator simply calls the appropriate constructor, according to the parameters passed to it, initializing all fields. Indeed, for structs it is
Dimensions point; point.Length = 3; point.Width = 6;
If
Dimensions
was a class, this would produce a compilation error, because
point
would contain an uninitialized reference - an address that points nowhere, so you could not start setting values to its fields. For a struct, however, the variable declaration actually
Dimensions point; Double D = point.Length;
Structs follow the same rules as any other data type: everything must be
The fact that structs are value types will affect performance, though depending on how you use your struct, this can be good or bad. On the positive side, allocating memory for structs is very fast because this takes place inline or on the stack. The same goes for removing structs when they go out of scope. On the other hand, whenever you pass a struct as a parameter or assign a struct to another struct (as in
A=B
, where
A
and
B
are structs), the full contents of the struct are copied, whereas for a class only the reference is
Structs are not designed for inheritance. This means that it is not possible to inherit from a struct. The only exception to this is that structs, in common with every other type in C#, derive ultimately from the class
System.Object
. Hence, structs also have access to the methods of
System.Object
, and it is even possible to override them in structs - an obvious example would be overriding the
ToString()
method. The actual inheritance chain for structs is that each struct derives from a class,
System.ValueType
, which in
You can define constructors for structs in exactly the same way that you can for classes, except that you are not permitted to define a constructor that takes no parameters. This may seem
That said, the default constructor, which initializes all fields to zero values, is always present implicitly, even if you supply other constructors that take parameters. It’s also
struct Dimensions { public double Length = 1; // error. Initial values not allowed public double Width = 2; // error. Initial values not allowed }
Of course, if Dimensions had been declared as a class, this code would have compiled without any problems.
Incidentally, you can supply a Close() or Dispose() method for a struct in the same way you do for a class.