Understanding and using object-oriented coding techniques is the key to building well-crafted C# applications. In this part of the C# tutorial, we will talk about object-oriented programming in C#.
C# is an object-oriented programming (OOP) language. OOP includes classes, objects, overloading, encapsulation, data hiding, and inheritance. All OOP languages provide mechanisms that help you implement the object-oriented model. They are encapsulation, inheritance, polymorphism, and reusability.
- OOPS Concepts In C#
- C# Classes and Types
- C# Inheritance
- C# Abstract Classes
- C# Interfaces
- Difference Between Abstract Class And Interface In C#
- C# Nested Classes
- C# Structs
- C# Namespaces
OOPS Concepts In C#
C# provides full support for object-oriented programming including encapsulation, inheritance, and polymorphism.
Objects are a fundamental encapsulation mechanism of object-oriented languages (OOLs).
- objects - encapsulate data together with operations, called methods that process or act upon the data.
OOLs may provide additional encapsulation mechanisms.
- classes - create objects that all have the same members and the same implementation of methods.
- packages - group together classes that work closely with each other. nested objects and classes - allow objects or classes to access private members of the objects or classes in which they are nested.
Inheritance describes the ability to create new classes based on an existing class.
There are two types of inheritance in OOLs
- interface inheritance and
- implementation inheritance.
Interface inheritance is only necessary for typed OOLs. This is best understood when considering delegation-based design patterns.
Implementation inheritance mechanisms depend on the type of OOL.
For class-based OOLs, classes inherit from classes.
Polymorphism means that you can have multiple classes that can be used interchangeably, even though each class implements the same properties or methods in different ways.
Most non-object-oriented programming languages provide if, if..else and case or switch statement forms as alternation constructions.
In object-oriented languages there is another alternation construction: send a message to a variable. You get different code to execute by assigning a new object to the variable. The different objects that can be assigned to a variable can respond to the message in different ways. This idea is lies at the heart of many design patterns.
The rest of the sections describes how to apply these three core OOP concepts using C#.
C# Classes and Types
As we noted previously, one can create new reference types by defining classes. Classes provide ‘templates’ from which these direct instances are generated. Where we appeal to the relation between a class and its corresponding reference type instances we shall say that a class specifies the type (also that the class specifies the constitutive elements of the type).
Any type is made up of elements, which we term type members. There are two main kinds of type members that a class can specify. Firstly, a class can specify other types - both value and reference (for the distinction see C# Variable Types). This idea, that types can contain other types, is known within the literature on object orientation as ‘containment’, or else ‘aggregation’. Where a type contains another reference type, we shall call it the containing type of the latter.
The second, main kind of type members that a class can specify are methods, functions designed for reading and manipulating the value and reference types an instance contains.
Object oriented languages like C# allow inheritance from reference types. If a type inherits from another, it takes on all of its type members. A type can, however, both add to the members it inherits in this way, as well as ‘overwriting’ them. To overwrite a type member - a method, say - the defining class specifies a method with the same name as one that it inherits (this is covered in future articles).
C#’s inheritance model is more similar to Java’s than to C++’s. In particular, C# classes inherit always from a single base class (if one is not specified in the declaration, inheritance is from System.Object). At the same time, however, C# classes can inherit from any number of interfaces.
C# Abstract Classes
Some classes are not designed to have direct instances. Rather, they are designed simply to be inherited from, by ancestors which may themselves have direct instances (or not). A class is ‘abstract’ just in case it cannot itself have direct instances.
Classes can be abstract because in a class it is possible to specify a class method without specifying its body. Such methods are themselves termed ‘abstract’. Where a class contains an abstract method it cannot be instantiated since it is not specified what should happen were the method to be called.
An interface is more like a contract that has only abstract methods. An interface is declared with the
interface keyword. Above we stated that a C# class can only inherit from one base class, but this ignores interfaces. A class can inherit from any number of interfaces.
Also, all the members of the interface must be implemented in a class or struct. C# will give a compile-time error if any one of the members is not defined.
Difference Between Abstract Class And Interface In C#
|It contains both declaration and definition part.||It contains only a declaration part.|
|Multiple inheritances are not achieved by an abstract class.||Multiple inheritances are achieved by the interface.|
|It contains a constructor.||It does not contain a constructor.|
|It can contain static members.||It does not contain static members.|
|It can contain different types of access modifiers like public, private, protected, etc.||It only contains public access modifier because everything in the interface is public.|
|The performance of an abstract class is fast.||The performance of the interface is slow because it requires time to search the actual method in the corresponding class.|
|It is used to implement the core identity of the class.||It is used to implement the peripheral abilities of the class.|
|A class can only use one abstract class.||A class can use multiple interfaces.|
|If many implementations are of the same kind and use common behavior, then it is superior to use an abstract class.||If many implementations only share methods, then it is superior to use Interface.|
|An abstract class can contain methods, fields, constants, etc.||Interface can only contain methods.|
|It can be fully, partially or not implemented.||It should be fully implemented.|
C# Nested Classes
Classes are usually specified independently of each other. But one class can be specified within another’s specification. In this case, the latter class is termed a nested class.
A struct is a user-defined value type. It is declared in a very similar way to a class, except that it can’t inherit from any class, nor can any class inherit from it (as mentioned previously, however, all value types do inherit from System.object). The following example shows a partial declaration for a ‘Coordinate’ struct:
Given the above, one could familiarly initialize a Coordinate type, using code like:
Note that if a variable of a struct type is declared without being given an explicit value, eg:
it does not equate to ‘null’ (this being the default value for reference types, rather than value types). Instead, the variable is initialized to a state where its fields have their default values. If these fields are basic value types, they will generally be set to zero. If these fields are reference types, they will be set to ‘null’.
Because of this default initialization behavior, it is an error for a struct to be given a parameterless constructor (eg. one like ‘public Coordinate()’). Also, where a struct does have a constructor, you should be sure to make assignments to all of the struct’s fields within this constructor.
Namespaces can be thought of as collections of classes; they provide unique identifiers for types by placing them in a hierarchical structure.
To illustrate the use of namespaces: suppose that two different C# developers come up with a class called ‘bank’, one relating to fiscal institutions and the other relating to riversides. In a programming environment containing both classes, there is a need to distinguish one from the other, and this is achieved by placing them within different namespaces. For example, the former class could be placed within the ‘fiscal’ namespace, say, becoming fiscal.bank, whereas the latter could be placed within the ‘river’ namespace becoming river.bank. (Note that C# does not include Java’s direct link between the namespace hierarchy and the file structure hierarchy).
Most classes depend upon the existence of other classes - for instance, they may specify contained types. It is possible in the specification always to write each class’ full namespace, but these are often too long for it to be worthwhile. To take an example at random, the following is the fully qualified name of a class in the .NET framework relating to a particular type of cryptographic algorithm:
This problem is addressed by the use of the ‘using’ keyword, placed at the very top of the class specification. For instance, in a class specification including the phrase
one could write refer to the above class simply using its class name
Alternatively, one could specify an alias for the namespace, eg
and then refer to the class with
One specifies a namespace for one’s classes using the ‘namespace’ keyword. For instance, the following code states that the class ‘Adder’ is in the namespace
Alternatively, and more simply, one write the above as:
In the following articles we will learn about C# Classes, Methods and Polymorphism in more detail.
Subscribe to Code with Shadman
Get the latest posts delivered right to your inbox