A class is a blueprint, which means it contains the members and methods that the instantiated objects will have. An interface can also be categorized as a blueprint, but unlike a class, an interface doesn’t have any method implementation. Interfaces are more like a guideline for classes that implement the interface.
The main features of interfaces in C# are as follows:
- Interfaces can’t have a method body; they can only have the method signature.
- Interfaces can have methods, properties, events and indexers.
- An interface can’t be instantiated, so no object of an interface can be created.
- One class can extend multiple interfaces.
One of the major uses of an interface is dependency injection. By using interfaces, you can reduce the dependencies in a system.
Let’s look an example of an interface
In the preceding example, we can see that we have one interface, called IBankAccount, that has two members: Debit and Credit. Both of these methods have no implementations in the interface. In the interface, the method signatures are more like guidelines or requirements for the classes that will implement this interface. If any class implements this interface, then the class has to implement the method body.
This is a great use of the OOP concept of inheritance. The class will have to give an implementation of the methods that are mentioned in the interface. If the class doesn’t implement any of the methods of the interface, the compiler will throw an error that the class has not implemented all the methods of the interface. By language design, if an interface is implemented by a class, all the members of the interface must be taken care of in the class.
An abstract class is a special kind of class that comes with the C# programming language. This class has similar functionalities to an interface. For example, an abstract class can have methods without implementation and with implementation. Consequently, when a class implements an abstract class, the class has to override the abstract methods of the abstract class. One of the main characteristics of an abstract class is that it can’t be instantiated. An abstract class can only be used for inheritance. It might or might not have abstract methods and assessors. Sealed and abstract modifiers can’t be placed in the same class, as they have completely separate meanings.
Let’s take a look at an example of an abstract class
In the preceding example, we saw that the Dog class is implementing the Animal class, and as the Animal class has an abstract method called Move(), the Dog class must override it.
You can split a class, a struct, or an interface into smaller portions that can be placed in different code files. If you want to do this, you have to use the keyword partial. Even though the code is in separate code files, when compiled, they will be treated as one class altogether. There are many benefits of partial classes. One benefit is that different developers can work on different code files at a time. Another benefit is that if you are using autogenerated code and you want to extend some functionality of that autogenerated code, you can use a partial class in a separate file. Consequently, you are not directly touching the autogenerated code, but adding new functionality in the class.
The partial class has a few requirements, one of which is that all classes must have the keyword partial in their signatures. All the partial classes also have to have the same name, but the file names can be different. The partial classes also have to have the same accessibility, such as public, private, and so on. This will increase the readability of your code, and your code organization will be more structured.
One of the principles of OOP is inheritance, but sometimes you may need to restrict inheritance in your code for the sake of your application’s architecture. C# provides a keyword called sealed. If this keyword is placed before a class’s signature, the class is considered a sealed class. If a class is sealed, that particular class can’t be inherited by other classes. If any class tries to inherit a sealed class, the compiler will throw an error. Structs can also be sealed, and in that case, no class can inherit that struct.
If we try to create a Dog class that will inherit the Animal class, as in the following code, then the compiler will throw an error “Dog: can not derive from sealed type Animal”, saying that the sealed Animal class can’t be inherited.
A tuple is a data structure that holds a set of data. Tuples are mainly helpful when you want to group data and use it. Normally, a C# method can only return one value. By using a tuple, it is possible to return multiple values from a method. The Tuple class is available under the System.Tuple namespace. A tuple can be created using the Tuple<> constructor or by an abstract method named Create that comes with the Tuple class. You can fix any data type in a tuple and access it using Item1, Item2, and so on.
For security reasons, all the fields of a class shouldn’t be exposed to the outside world. Consequently, exposing private fields is done by properties in C#, which are members of that class. Underneath the properties are special methods that are called accessors. A property contains two accessors: get and set. The get accessor gets values from the field while the set accessor sets values to the field. There is a special keyword for a property, named value, this represents the value of a field. By using access modifiers, properties can have different access levels.
A property can be public, private, read only, open for read and write, and write only. If only the set accessor is implemented, this means that the only write permission is given. If both set and get accessors are implemented, this means that both read and write permissions are open for that property. C# provides a smart way of writing setter and getter methods. If you create a property in C#, you don’t have to manually write setter and getter methods for a particular field. Consequently, the common practice in C# is to create properties in a class, rather than creating fields and setter and getter methods for those fields.
The convention is that properties should be in camel case. When you create a property in camel case, a field with the same name is created internally, but in Pascal case. The value is a special keyword that actually represents the value of that property. Properties are working behind the scenes in the background, which makes the code much cleaner and easier to use. It’s very much recommended that you use properties instead of local fields.
Acces Modifiers for Classes
Access specifiers, or access modifiers, are some reserved keywords that determine the accessibility of a class, method, property, or other entity. The object oriented principle of encapsulation is achieved by using these
access specifiers in C#. In total, there are five access specifiers.
The public access specifier means that there is no limitation to access the entity being modified. If a class or member is set as public, it can be accessed by other classes or programs in the same assembly, other assemblies, and even other programs that are installed in the operating system that the program is running in. Normally, the starting point of an application or main method is set as public, meaning that it can be accessed by others. To make a class public, you just need to put a public keyword before the keyword class.
The private specifier is the most secure access specifier available in the C# programming language. By setting a class or member of a class as private, you are determining that the class or the member won’t be allowed to be accessed by other classes. The scope of a private member is within the class. For example, if you create a private field, that field can’t be accessed outside the class. That private field can only be used internally in that class.
If you set internal as an access specifier, this means that the entity is only accessible within the same assembly. All the classes in the assembly can access this class or member. When you build a project in .NET, it creates an assembly file, either dll or exe. There could be many assemblies in one solution, and internal members are only accessible by the classes on those particular assemblies.
Protected members are accessible by the class itself, as well as the child classes that inherit the class. Other than that, no other class can access a protected member. The protected access modifier is very useful when inheritance takes place.
A protected internal is a combination of a protected access modifier and an internal access modifier. A member whose access modifier is protected internal can be accessed by all classes in the same assembly, as well as by any class that inherits it, regardless of the assembly. For example, say that you have a class named Animal in an assembly called Assembly1.dll. In the Animal class, there is a protected internal method called GetName. Any other class in Assembly1.dll can access the GetName method. Now, suppose there is another assembly named Assembly2.dll. In Assembly2.dll, there is a class named Dog that extends the Animal class. As GetName is a protected internal, even though the Dog class is in a separate assembly, it can still access the GetName method.