Many times on the forum people have asked about the differences between structs and their big brother “classes”. How do the two differ and where are they the same? How do I know when I need one or the other and why don’t I just use classes all the time? We will attempt to explore the differences from a basic introductory standpoint so that the beginner can understand. We will talk about the fundamental difference between their types, where they fit in with inheritance, and covering constructor use. The smackdown is on! Right here on the Programmer’s Underground!
Ok, so what is a struct and what is a class and how do they differ?
Well a class is the fundamental idea of an object, a blueprint if you will, telling the computer how to build an object and how it works in the program. Classes are meant to mimic what humans perceive of the world around them and put it in such a way that a computer can understand too. Our mental picture of the world is made up of objects and we have expectations of how those objects behave and what they might look like. We then classify them in our minds so that they can be stored away in memory… building what is known as our “lens of the world”. This lens is different for everyone and is built through experiences in our lives. It is our mental picture of the world, the rules that govern it (like gravity or that people should not hate one another) and is constantly tuned by our mind every second of every day. When I say “car” you automatically pull the idea of an object with four or more wheels, a steering wheel, doors, engine and maybe even a color. This object was built and refined over time with your experience seeing and dealing with cars.
Computers on the other hand have no clue what a car is. They don’t see them or touch them or even have an idea what they are for. Classes tell them how they work and what kind of properties they have. If you tell the computer that a car has a monster mounted to the top, it would believe you with no question. Classes contain properties (we know them as descriptions of the object) and they have methods (actions… we know a car can be driven).
Structs are fundamentally the same thing as classes, but on a more scaled down basis. They represent a more basic item and are used in programming when we don’t need a big item to be built. Structs can have functions, member variables, properties and even a constructor (talked about later). Why build this bulky big class to describe something as simple as a solid block of stone. It just sits there, it has probably a few dimensions (width, height, depth) and maybe a color (gray). Using an class would be more time and effort than is needed.
Now that we have a basic concept of a class and a struct, lets go into some differences…
1) Classes are known as reference types, structs are known as value types.
When you create a class it is put into a particular place in memory known as the heap. In C# this heap is managed and makes sure that the rules of an object are obeyed. The heap can be quite large in size because the objects it controls are often “heavy” or contain a lot of data members, functions, abilities etc. To pass them around in a program and copy them can cause a bit of overhead, slowing things down. These types of objects are considered reference types because you don’t move them around, you move around references to them in memory. Instead of copying the object from section 1 to section 5 in memory, you often use methods that pass around references (variables that say “hey, that object is found in section 1 over there”).
On the other hand when you create a struct, it is put into a particular place in memory known as the stack. Structs, as already mentioned, are scaled down versions of classes and considered “light”. They are also defined as “value types”. Meaning that because they are light and small in size, moving them around in memory doesn’t cause much overhead (unless they are contain too much data) and can be moved from place to place quickly and easily.
2) Classes can inherit and structs can not (from user defined base classes).
The idea of inheritance goes back all the way to the beginnings of object oriented programming. To use our example from before with the car, you could say that a car is a type of vehicle. It is a more specialized type of vehicle. So instead of defining a vehicle every time you want a car, you inherit the idea of a vehicle and then just add on the functionality for a car. Perhaps the definition of a vehicle is a machine with an engine. Cars have engines… so when you define the blueprint of a car, you inherit from vehicle and the program already knows that your car is going to have an engine. You then tell it that a car has four wheels etc.
[i]Note: In languages like C++ you were able to inherit from multiple classes. A car might inherit from a vehicle, but it might also inherit from a machine. This made for powerful classes, but introduced some tricky traps later. So Microsoft decided to make C# inherit only from a single parent class.[/i]
When you inherit you get a reference to the vehicle class which is used in the definition of the car class. You are saying “Hey, build a vehicle, then add this stuff to make it a car.” Since you are using a reference, you can assume that structs are not going to be doing inheritance. But why would you want to do inheritance anyways with a struct? structs are simple items, easily built and thus don’t need to reference anything. What is the block of stone going to inherit? It has three dimensions and a color. Not much more to it.
3) Classes are inherited directly from the base class “object” and structs are inherited indirectly through “valuetype”
Going back to the inheritance discussion in point 2, classes and structs describe objects we know about. All classes in C# derive from the fundamental base class called “object”. Classes inherit this automatically without you even asking. Structs on the other hand inherit from object, but indirectly through an object called “System.ValueType”. This class tells structs how to act as the value type of object and to be stored on the stack. Hence the difference mentioned in point 1 above.
4) Structs have constructors too, just not always the same ones as classes.
Constructors are a simple method of a class or a struct that has the same name. They are used to put the object into a known valid state. If we are building a car object, think of the constructor saying “ok, this car will start out red and it will be put into park”. A code example of this is below…
public class Car { private string color; private string gear; // Our constructor below, notice no info is given to it (parameterless). // This would not be allowed in structs public Car() { this.color = "red"; // Put the car into a state of being red upon creation this.gear = "park"; // Put the car into a state of being in park } }
Remember that structs are essence the same as classes, but scaled down. They can have constructors too, to initialize member data, but in C# they are not allowed to have a no parameter constructor. But what the hell?!?!?! Why not? The short answer is, the .NET runtime (the framework behind the compiler) just can’t handle the thought of a parameterless constructor on a struct and problems could arise. So they made the language to not accept parameterless constructors that you define. HOWEVER, it does create a default constructor in the background no matter if you provide other constructors (ones with parameters) or not.
5) Watch the size of your structs. If they get too big, make them classes.
So you might be thinking, hey, why not use structs and just make them large like classes? The problem with this is that they were stored on the stack and come from the valuetype object which tells them to behave differently. When you pass them around from function to function, the program is making copies of the struct each time instead of passing around a reference to it. If you make the struct too big, the program is spending too much time copying the data around than executing other code. So you will notice your programs will start to slow down. You will get a performance problem really quick.
If you find the struct growing beyond a few data members and a couple functions, it might be a good idea to make it a class then. If you think you might also need to expand a struct in the future into something bigger, you might want to make it a class from the beginning. If that block of stone is going to be eventually chizzled into a beautiful fountain statue, make the block a class so that someone can come along and tell it how to become a statue that spits water or pees water or has water running out from other parts or whatever.
So after all these points, the one thing to really remember is that structs and classes are fundamentally the same. Structs are scaled down versions of classes, are used like other value types (like integers or doubles) and cannot inherit. If you need something a bit more robust, could be a little more detailed, or may be expanded in the future into something much more complex, you want to go with a class.
Quick Conclusion
I hope these points have helped you realize the difference between the two. They both have their advantages and disadvantages, but pick carefully when to use each and you will enjoy the benefits of both.
Thanks for reading! 🙂