A type that is defined as a class is a reference type. Classes are creatd using the class
keyword.
A simple class is created like this:
class MyClass
{
// Code of your class
}
It generally contains a creator that will specify how to create the instance of the class and some variable:
class MyClass
{
private int myClassVariable;
public MyClass(){
// Code of you Class Creator
}
public void myClassMethod() {}
}
Fields (also called attributes or variables) and methods inside classes are often referred to as members:
If the class inherit from another class or interface (a class can inherit from only on parent class but from multiple interfaces) the class creation is a little bit more complex:
interface IHobby
{
public string Hobby { get; set; }
}
interface IHaircut
{
public string HairColor { get; set; }
public void printHairColor();
}
class Person
{
public int age;
public void printAge() { Console.WriteLine($"Person age is: {age}"); }
}
// A Footballer is a personne with a haircut and hobby
class Footballer: Person, IHaircut, IHobby
{
public string HairColor { get; set; } // A class must implement all members of interfaces from which it derived
public string Hobby { get; set; } // A class must implement all members of interfaces from which it derived
public Footballer(int age, string hairColor, string hobby)
{
this.age = age;
this.HairColor = hairColor;
this.Hobby = hobby;
}
public void printHairColor() { Console.WriteLine($"Hair Color is: {HairColor}"); }
}
class MyClass { }
MyClass myClass = new MyClass();
All the following instanciations methods also work:
class MyClass
{
public int myInt;
public string myString;
public MyClass() { }
public MyClass(int varInt) { myInt = varInt; }
public MyClass(string varString) { myString = varString; }
public MyClass(int varInt, string varString) { myInt = varInt; myString = varString; }
}
MyClass myClass11 = new MyClass();
MyClass myClass12 = new MyClass(1);
MyClass myClass13 = new MyClass("text");
MyClass myClass14 = new MyClass(1, "text");
MyClass myClass21 = new MyClass() { myInt = 1 , myString = "text"};
MyClass myClass22 = new MyClass(1) { myString = "text"};
MyClass myClass23 = new MyClass("text") { myInt = 1 };
MyClass myClass24 = new MyClass(1, "text");
Non virtual
or abstract
methods can’t be overriden.
class Person
{
public int age;
public Person(int age) {
this.age = age;
}
public void printAge() { Console.WriteLine($"Person age is: {age}"); }
}
class Footballer: Person
{
public Footballer(int age) : base(age) { }
// Can't override printAge function
}
Footballer footballer = new Footballer(30);
footballer.printAge() // Person age is: 30
virtual
methods from parents class may be overriden using the override
keyword.
class Person
{
public int age;
public Person(int age) {
this.age = age;
}
public virtual void printAge() { Console.WriteLine($"Person age is: {age}"); }
}
class Footballer: Person
{
public Footballer(int age) : base(age) { }
// Not mandatory to override the function
public override void printAge() { Console.WriteLine($"Footballer age is: {age}"); }
}
Footballer footballer = new Footballer(30);
footballer.printAge() // Footballer age is: 30
abstract
methods from abstract parents class must be overriden using the override
keyword. A non abstract class can’t have abstract
(ie undefined) methods.
abstract class Person
{
public int age;
public abstract void printAge();
}
class Footballer: Person
{
public Footballer(int age) {
this.age = age;
}
public override void printAge() { Console.WriteLine($"Footballer age is: {age}"); }
}
Footballer footballer = new Footballer(30);
footballer.printAge() // Footballer age is: 30
There exist different types of class in C#. The basic behaviour of
class MyClass { }
A Static Class cannot instantiate objects with the new
keyword, and class members can only be accessed by using the actual class name.
static class MyClass {
static public int myClassStaticVariable = 1;
}
Console.WriteLine(MyClass.myClassStaticVariable); // 1
Every member of a static class must also be declared as static.
Abstract class cannot be used to create objects directly. An abstract class is just a template for its children classes. Children classes of an abstract class can be instantiate.
abstract class MyClass
{
public int myClassVariable = 1;
public void printVariable() { Console.WriteLine(myClassStaticVariable); }
public abstract void printVariableSquared();
}
class MyChildClass: MyClass
{
public override void printVariableSquared() {Console.WriteLine(myClassStaticVariable * myClassStaticVariable)}
}
MyChildClass myChildClassInstance = new MyChildClass();
Console.WriteLine(myChildClassInstance.myClassVariable); // 1
Partial Class allows methods, events, and properties to be split into separate/multiple .cs source files, which are combined into one class at compile time.
In file1.cs:
partial class MyClass {
public int myClassVariable1 = 1;
}
In file2.cs:
partial class MyClass {
public int myClassVariable2 = 2;
}
Sealed classes are used to restrict the inheritance feature of object-oriented programming. Once a class is defined as a sealed class, this class cannot be inherited.
sealed class MySealedClass {}
Access modifiers are keywords that modify the rights to access class, attributes and methods.
Each of these keywords may be applied to the class itself, to its attributes or to its methods.
The default accessibility of class members in C# is private (see Microsoft page on accessibility levels).
Public attributes and methods are accessible from anywhere in the code.
class MyClass {
public int publicAttribute;
public void publicMethod() {}
}
Private attributes and methods are only accessible from within the class.
class MyClass {
private int privateAttribute;
private void privateMethod() {}
}
Protected attributes and methods are only accessible by class members and classes that inherit from it.
class MyClass {
protected int privateAttribute;
protected void privateMethod() {}
}
Internal attributes and methods are only accessible at the current assembly point of the class.
class MyClass {
internal int privateAttribute;
internal void privateMethod() {}
}
The default accessibility of a class is internal. A class can’t be declared as private.
A public class is accessible from anywhere in the code.
public class MyClass { }
A protected class is only accessible by class members and classes that inherit from it. It is not used a lot but here is an example (example from StackOverflow):
class MyParentClass {
protected class ProtectedClass { }
}
class MyChildClass: MyParentClass {
private void methodCallingProtectedClass(Outer.Foo foo) { } // OK
}
class MyOtherClass {
private void methodCallingProtectedClass(Outer.Foo foo) { } // ERROR: Access error
}
Here, the ProtectedClass is accessible from MyChildClass as MyChildClass inherits (derives) from MyParentClass but it is not accessible from MyOtherClass.
An internal class is only accessible at the current assembly point of the class.
internal class MyClass { }
A property is a member that provides a flexible mechanism to read, write, or compute the value of a private field. Properties can be used as if they’re public data members, but they’re special methods called accessors. This feature enables data to be accessed easily and still helps promote the safety and flexibility of methods. (from Microsoft page on C# properties).
Properties can be read-write, readable only or writable only (this one is less common).
get
and set
functions are used to respectively read and write data through the Property.
The get
and set
are accessed transparantly by just calling the Property.
public class MyClass {
public string Name { get; set; } // Basic get and set: returns the value of Name and write to the value of Name
}
MyClass myClass = new MyClass();
myClass.Name = "Henry";
Console.WriteLine(myClass.Name); // Henry
public class MyClass {
private string _name;
public MyClass(string name) {
_name = name;
}
public string Name {
get => _name;
set => _name = value;
}
}
MyClass myClass = new MyClass("John");
Console.WriteLine(myClass.Name); // John
myClass.Name = "Henry";
Console.WriteLine(myClass.Name); // Henry
public class TimePeriod {
private double _seconds; // can't access this field outside the class, must use Hours
public double Hours {
get { return _seconds / 3600; }
set {
if (value < 0 || value > 24)
throw new ArgumentOutOfRangeException(nameof(value), "The valid range is between 0 and 24.");
_seconds = value * 3600;
}
}
TimePeriod timePeriod = new TimePeriod();
timePeriod.Hours = 5; // transform and store data in _seconds
Console.WriteLine(timePeriod.Hours); // 5: retrieve data from _seconds and transform it in hours
}
public class MyClass {
public required string Name { get; set; }
}
MyClass myClass = new MyClass { Name = "Henry" };
Console.WriteLine(myClass.Name); // Henry
When inheriting from an interface, the override of the method may be implicit or explicit.
Implicit override is the classic way of inheriting an interface method.
interface ISampleInterface {
void SampleMethod();
}
class ImplementationClass : ISampleInterface {
public void SampleMethod() {
Console.WriteLine("Implementation of interface method.");
}
}
/* You can instanciate an object of class ImplementationClass and call the method SampleMethod */
ImplementationClass obj = new ImplementationClass();
obj.SampleMethod(); // "Implementation of interface method."
interface ISampleInterface {
void SampleMethod();
}
class ImplementationClass : ISampleInterface {
void ISampleInterface.SampleMethod() { Console.WriteLine("Implementation of interface method."); } // Should not reuse public keywork
}
/* You can't instanciate an object of class ImplementationClass using ImplementationClass constructor and call the method SampleMethod */
/* You need to instanciate a ISampleInterface object using ImplementationClass constructor to call SampleMethod */
ISampleInterface obj = new ImplementationClass();
obj.SampleMethod(); // "Implementation of interface method."
See Boxing and Unboxing Class Examples.
See: