Huw Collingbourne

C# is one of the most widely used object-oriented programming (oop) languages. But what exactly is object orientation, and how can it be used in C# programs? 

Let’s first consider what an ‘object’ actually is. In essence, an object is a structure that is able to contain both data and behavior. All the data items in a C# program – from a string such as “Hello world” to a treasure in a game – are wrapped up inside objects.

In addition to data, an object may also contain functions, which are called ‘methods’ in object-oriented terminology. You can use these methods to manipulate the object’s data. For example, I might write a function called ToUpper() to return a string in upper case or a function called TimesTen() to return an integer value multiplied by 10.

Person coding on laptop

Classes and Objects

You create each object from a ‘class.’ You can think of a class as a blueprint that defines both the data (the variables) and the object’s behavior (the methods). Let’s look at an example of a very simple class definition:

class MyClass {
	private string _s;
 
	public MyClass() {
    	_s = "Hello world";
	}
 
	public string GetS() {
    	return _s;
	}
 
	public void SetS(string aString) {
    	_s = aString;
	}
}
Learn C# Programming (In Ten Easy Steps)

Last Updated August 2019

  • 126 lectures
  • Beginner Level
4.3 (1,114)

The simplest way to learn C# programming. | By Huw Collingbourne

Explore Course

A class is defined using the class keyword. Here I have decided to call the class MyClass. It contains a string, _s. I’ve made this string ‘private,’ meaning code outside the class cannot access the string variable. To access the string, any code outside the class must use the methods I’ve written for that purpose – GetS() and SetS(). Sometimes an object is termed an ‘instance’ of a class.

Encapsulation and Data Hiding

The ability to put both data and functions into a class is called ‘encapsulation.’ In non-object-oriented languages, functions are ‘free-standing,’ meaning objects do not contain them.

At a simple level, encapsulation can be thought of as a way of structuring code more neatly. However, to realize the full power of encapsulation, you need to do ‘data-hiding.’ This is what I’ve done in the code above by making the _s variable private. That variable now hides from code outside MyClass. To set or get the value of _s, you must use the public data-access methods: GetS() and SetS().

A strictly encapsulated object is like a sealed box. From outside the box, you can’t see what it contains. All you know is its behavior. You send it messages. It returns replies – like an old-style mainframe computer into which punched cards were fed (messages) and from which rolls of printed output were produced (replies). This process makes it possible for a programmer who writes a class to be certain that other programmers are obliged to use well-defined routes into and out of that class, avoiding bugs that may be caused by making unexpected or invalid changes to data. Encapsulation with data-hiding is sometimes called ‘black box encapsulation.’

Accessing Data With Methods

By using methods to access variables, you are able to test that data is valid (before assigning or returning values) and control how much access is permitted to the variables inside an object. A method could, for example, restrict the amount of currency that can be returned from an internal variable called some_money, whereas if that variable were public and so could be accessed directly, the user would be able to withdraw any amount of currency with no limit.

At this point, the MyClass class doesn’t actually do anything. It is simply a definition or ‘blueprint’ for objects which don’t yet exist. In order to use the MyClass class, I need to create an object from it. To do that, I start by declaring an object variable of the MyClass type:

MyClass ob;

But before I can use the object, I need to create it. I do that by using the new keyword. This calls the MyClass constructor method, and that returns a new MyClass object which I here assign to the ob variable:

ob = new MyClass();

Constructors

A constructor is a special method that, in C#, has the same name as the class itself. This is the MyClass constructor:

public MyClass() {
	_s = "Hello world";
}

The code in this constructor assigns the string “Hello world” to the variable _s. You aren’t obliged to write any code in a constructor. However, it is quite common – and good practice – to assign default values to an object’s ‘fields’ or variables in the con­structor. I have also written a SetS() method:

public void SetS(string aString) {
	_s = aString;
}

You can call SetS() when you want to change the default value of each object’s _s string variable:

ob.SetS("A new string");

And you can retrieve the value of the _s variable using the GetS() method:

textBox1.Text = ob.GetS();

Classes, Objects, and Methods

Let’s quickly summarize the essential details of classes, objects, and methods. A ‘class’ is the blueprint for an object. It defines the data an object contains and the way it behaves. The following is a very simple C# class to define a Car:

class Car {
	private string _name;
	private int _speed;
}

In the real world, you can’t drive the blueprint of a car. Someone has to construct a usable car from the definition provided by the blueprint. In a C# program, we would need to create a usable Car object from the definition provided by the Car class.

Constructing Objects

Whenever we construct a new Car object, it needs to be assigned a name and a speed. In C#, I do that in the constructor method called Car():

class Car {
	private string _name;
	private int _speed;
 
	public Car() {
    	_name = "Generic Car";
    	_speed = 0;
	}
}

The constructor assigns default values (“Generic Car” and 0) to the private fields (_name and _speed) of each newly constructed Car object. I can construct numerous different Car objects by calling the constructor after the new keyword and then assigning each new Car object to a Car variable. Here I create three Car objects:

Car car1;
Car car2;
Car car3;
 
car1 = new Car();
car2 = new Car();
car3 = new Car();

This is the programmatic equivalent of constructing three cars from a single blueprint. Having constructed some Car objects, I now want to change their default names and speeds. I can do that using methods. Remember that a ‘method’ is just the object-oriented word to describe a function or subroutine defined inside a class. These are my methods to change (to get and to set) the speed of a Car object:

public int GetSpeed() {
	return _speed;
}

public void SetSpeed(int aSpeed) {
	_speed = aSpeed;
}

I can call a method by writing the name of an object, followed by a dot, the name of a method and a pair of parentheses (with any arguments – that is, the data to be sent to the constructor) and a semicolon, like this:

car1.SetSpeed(80);
car2.SetSpeed(120);
car3.SetSpeed(100);

Inheritance

Inheritance is one of the key features of object-orientation. The idea is that you create a simple class, then define more specialized classes that inherit all the features of that class and add on additional features of their own. That means you don’t have to re­code the same features repeatedly. Features of ‘ancestor’ classes are automati­cally ‘inherited’ by descendant classes.

For example, you could create a ‘family tree’ of Car classes. A SportsCar might inherit all the features of a Car but add on two extra features: TurboThruster and GoFasterStripe. Another class called LuxuryCar might also descend from the Car class. It would add on the additional features: DeluxeUpholstery and IntegralCocktailCabinet.

Class Hierarchies

To create a descendant of a class, you need to put a colon : plus the ancestor class (or ‘base class’) name after the name of the descendant class, like this:

public class Treasure : Thing

A descendant class inherits its ancestor’s features (the methods and variables), so you don’t need to recode them. Here is some C# code that you might write for a game. It defines a base class called Thing and a Treasure class which descends from the Thing class:

public class Thing {
	private string _name;
	private string _description;
 
	public Thing(string aName, string aDescription) {
    	_name = aName;
    	_description = aDescription;
	}
 
	public string Name {
    	get {
        	return _name;
    	}
    	set {
        	_name = value;
    	}
	}
 
	public string Description {
    	get {
        	return _description;
    	}
    	set {
        	_description = value;
    	}
	}
}
public class Treasure : Thing {
	private double _value;
 
	public Treasure(string aName, string aDescription, double aValue)
    	: base(aName, aDescription) {
    	_value = aValue;
	}
 
	public double Value {
    	get {
        	return _value;
    	}
    	set {
        	_value = value;
    	}
	}
}

Here the Thing class has two private variables, _name and _description (being private, you cannot access them from outside the class) and two public properties, Name and Description, to access those variables.

Properties

A property is a group of one or two special types of methods to get (return) or set (assign) the value of a variable. This is a typical definition for a property:

private string _name;
 
public string Name {
	get {
    	return _name;
	}
	set {
    	_name = value;
	}
}

Here _name is private, but Name is public. This means that code outside the class can refer to the Name property but not the _name variable. If you omit the get part of a property, it will be impossible for code outside the class to retrieve the current value of the associated variable. If you omit the set part, it will be impossible for code outside the class to assign a new value to the related variable – in other words, it will be ‘read-only.’

Building A Class ‘Tree’

I can create more than one descendent ‘branch’ from a class. Here, I create a Room class which is also a descendent of Thing so it too inherits Name and Description. It adds on four direction properties (and variables):

public Room(string aName, string aDescription, int aN, int aS, int aW, int anE)
	: base(aName, aDescription) {
	_n = aN;
	_s = aS;
	_w = aW;
	_e = anE;
}
 
public int N {
	get {
    	return _n;
	}
	set {
    	_n = value;
	}
}
 
public int S {
	get {
    	return _s;
	}
	set {
    	_s = value;
	}
}
 
public int W {
	get {
    	return _w;
	}
	set {
    	_w = value;
	}
}
 
 
public int E {
	get {
    	return _e;
	}
	set {
    	_e = value;
	}
}

Notice that, in order to initialize the data of its ‘superclass’ (that is, its immediate ancestor), both Treasure and Room need to pass the arguments required by the Thing constructor method. Here these are the aName and aDescription arguments. They are passed to the constructor of the superclass using the base keyword after the parameter list of the descendant class’s constructor, followed by a colon:

public Treasure(string aName, string aDescription, double aValue)

: base(aName, aDescription)

public Room(string aName, string aDescription, int aN, int aS, int aW, int anE)

: base(aName, aDescription)

This diagram represents my ‘class hierarchy’ with the Treasure and Room classes both descending from the Thing class and inheriting Name and Description. Treasure adds Value. Room adds N, S, W and E:

You aren’t restricted to just one ‘level’ of inheritance. I could go on to add subclasses of Room and Treasure. For example, I could create a Weapon class that descends from Treasure. The Weapon class would inherit all the features of its superclass (Treasure) and all other ancestors (here, its only other ancestor is Thing). It would not inherit features from classes that are not its ancestors, though (such as Room). So if I create a Weapon class that descends from Treasure, it would inherit Name, Description and Value. I could then add extra features specific to Weapon objects – such as DestructivePower.

In short, Object Orientation Programming in C# gives you the ability to wrap up data and methods using encapsulation and inherit existing classes’ behavior. Used carefully, this allows the programmer to create secure, reliable programs without too much code duplication.

Page Last Updated: April 2022

Top courses in C#

Programming Design Patterns For Unity - Write Better Code
GameDev.tv Team, Sam Pattuzzi
4.6 (453)
Complete C# Unity Game Developer 3D
Ben Tristem, Rick Davidson, GameDev.tv Team, Gary Pettie
4.8 (35,905)
Bestseller
C# Intermediate: Classes, Interfaces and OOP
Mosh Hamedani
4.5 (30,063)
Bestseller
Learn Parallel Programming with C# and .NET
Dmitri Nesteruk
4.4 (2,953)
Bestseller
RPG Core Combat Creator: Learn Intermediate Unity C# Coding
Ben Tristem, Rick Davidson, Sam Pattuzzi, GameDev.tv Team
4.8 (10,064)
Design Patterns in C# and .NET
Dmitri Nesteruk
4.4 (9,659)
Bestseller
Complete C# Masterclass
Denis Panjuta, Tutorials.eu by Denis Panjuta
4.6 (21,701)

More C# Courses

C# students also learn

Empower your team. Lead the industry.

Get a subscription to a library of online courses and digital learning tools for your organization with Udemy Business.

Request a demo

Courses by Huw Collingbourne

Ruby Programming for Beginners
Huw Collingbourne
4 (741)
Learn C# Programming (In Ten Easy Steps)
Huw Collingbourne
4.3 (1,114)
Learn To Program with Delphi and Object Pascal
Huw Collingbourne
4.4 (696)
Bestseller
Break Into The Programming Business
Huw Collingbourne
3.6 (67)
How to teach an online course
Huw Collingbourne
4.8 (292)
C Programming For Beginners
Huw Collingbourne
4.3 (4,005)
Java Programming – the Master Course
Huw Collingbourne
4.3 (285)
Ruby For Programmers
Huw Collingbourne
4.3 (360)
Advanced C Programming: Pointers
Huw Collingbourne
4.5 (2,719)

Courses by Huw Collingbourne