0% found this document useful (0 votes)
19 views37 pages

OOP Concepts in C# Explained

Uploaded by

bala vinothini
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views37 pages

OOP Concepts in C# Explained

Uploaded by

bala vinothini
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Unit 3 Object Oriented Programming concepts in C#

What is OOP?
OOP stands for Object-Oriented Programming.
Procedural programming is about writing procedures or methods that perform operations on
the data, while object-oriented programming is about creating objects that contain both data
and methods.
Object-oriented programming has several advantages over procedural programming:
 OOP is faster and easier to execute
 OOP provides a clear structure for the programs
 OOP helps to keep the C# code DRY "Don't Repeat Yourself", and makes the code
easier to maintain, modify and debug
 OOP makes it possible to create full reusable applications with less code and shorter
development time

What are Classes and Objects?


Classes and objects are the two main aspects of object-oriented programming.
Look at the following illustration to see the difference between class and objects:
class
Fruit
objects
Apple
Banana
Mango
So, a class is a template for objects, and an object is an instance of a class.
When the individual objects are created, they inherit all the variables and methods from the
class.
Classes and Objects
Everything in C# is associated with classes and objects, along with its attributes and
methods. For example: in real life, a car is an object. The car has attributes, such as weight
and color, and methods, such as drive and brake.
A Class is like an object constructor, or a "blueprint" for creating objects.

Create a Class
To create a class, use the class keyword:
Create a class named "Car" with a variable color:
class Car
{
string color = "red";
}
When a variable is declared directly in a class, it is often referred to as a field (or attribute).
It is not required, but it is a good practice to start with an uppercase first letter when naming
classes. Also, it is common that the name of the C# file and the class matches, as it makes our
code organized. However it is not required (like in Java).
Create an Object
An object is created from a class. We have already created the class named Car, so now we
can use this to create objects.
To create an object of Car, specify the class name, followed by the object name, and use the
keyword new:
Example:
Create an object called "myObj" and use it to print the value of color:
class Car
{
string color = "red";

static void Main(string[] args)


{
Car myObj = new Car();
[Link]([Link]);
}
}

Note that we use the dot syntax (.) to access variables/fields inside a class ([Link]).
Multiple Objects
You can create multiple objects of one class:

Example
Create two objects of Car:
class Car
{
string color = "red";
static void Main(string[] args)
{
Car myObj1 = new Car();
Car myObj2 = new Car();
[Link]([Link]);
[Link]([Link]);
}
}
Using Multiple Classes
You can also create an object of a class and access it in another class. This is often used for
better organization of classes (one class has all the fields and methods, while the other class
holds the Main() method (code to be executed)).
[Link]
[Link]
[Link]
class Car
{
public string color = "red";
}
[Link]
class Program
{
static void Main(string[] args)
{
Car myObj = new Car();
[Link]([Link]);
}
}
Did you notice the public keyword? It is called an access modifier, which specifies that
the color variable/field of Car is accessible for other classes as well, such as Program.

Encapsulation in C# is the practice of hiding the internal state of an object and requiring all
interaction to be performed through an object's methods or properties. This helps protect data
from unintended changes and provides controlled access.
The process of binding or grouping the State (i.e., Data Members) and Behaviour (i.e.,
Member Functions) together into a single unit (i.e., class, interface, struct, etc.) is called
Encapsulation in C#. The Encapsulation Principle ensures that the state and behavior of a unit
(i.e., class, interface, struct, etc.) cannot be accessed directly from other units (i.e., class,
interface, struct, etc.).

The Encapsulation Principle in C# is very similar to a Capsule. As a capsule binds its


medicine within it, in the same way in C#, the Encapsulation Principle binds the State
(Variables) and Behaviour (Methods) into a single unit called class, enum, interface, etc. So,
you can think of Encapsulation as a cover or layer that binds related states and behavior
together in a single unit
Example: Student Class
using System;
public class Student
{
// Private fields, not accessible directly from outside.
private string name;
private int age;
// Public property to access the name.
public string Name
{
get { return name; }
set { name = value; }
}
// Public property to access the age.
public int Age
{
get { return age; }
set
{
if (value > 0)
age = value;
else
throw new ArgumentException("Age must be positive");
}
}
}

class Program
{
static void Main()
{
Student student = new Student();
[Link] = "Ankita";
[Link] = 21;

[Link]("Name: " + [Link]);


[Link]("Age: " + [Link]);
}
}
In this example:
The actual fields (name and age) are private, preventing direct access from outside the class.
Properties (Name and Age) provide a controlled way to read and set these fields, including
validation if needed.
If someone tries to set an invalid age, an exception is thrown, demonstrating how
encapsulation can also enforce business logic.

What is Data Hiding in C#?


Data hiding or Information Hiding is a Process in which we hide internal data from outside
the world. The purpose of data hiding is to protect the data from misuse by the outside world.
Data hiding is also known as Data Encapsulation. Without the Encapsulation Principle, we
cannot achieve data hiding.
In simple words, we can also say that the process of defining a class by hiding its internal
data members from outside the class and accessing those internal data members only through
publicly exposed methods (setter and getter methods) or properties with proper validations is
called Encapsulation.
Types of Constructors
There are five types of constructors available in C#, they are as follows
 Default or Parameter Less Constructor
 Parameterized Constructor
 Copy Constructor
 Static Constructor
 Private Constructor
Default or Parameter less Constructors in C#
If a constructor method does not take any parameters, then we call that a Default or
Parameter Less Constructor. These constructors can be defined by a programmer explicitly or
else will be defined implicitly provided there is no explicit constructor under the class. So,
the Default or Parameter less Constructors are again classified into two types. They are as
follows:
 System-Defined Default Constructor
 User-Defined Default Constructor

System Defined Default or Parameterless Constructor in C#?


As a programmer, if we are not defined any constructor explicitly in our program, then by
default the compiler will provide one constructor at the time of compilation. That constructor
is called a default constructor and the default constructor is parameter less. The default
constructor will assign default values to the data members (non-static variables). As this
constructor is created by the system this is also called a system-defined default constructor.
The Employee class, we have created a few variables. And then from the Main method, we
created an instance of the Employee class and then printed the values of the variables.
using System;
namespace ConstructorDemo
{
class Employee
{
public int Id, Age;
public string Address, Name;
public bool IsPermanent;
}
class Test
{
static void Main(string[] args)
{
Employee e1 = new Employee();
[Link]("Employee Id is: " + [Link]);
[Link]("Employee Name is: " + [Link]);
[Link]("Employee Age is: " + [Link]);
[Link]("Employee Address is: " + [Link]);
[Link]("Is Employee Permanent: " + [Link]);
[Link]();
}
}
}
So, when you run the above code, you will see that default values based on the variable type
are being printed on the console as shown in the below image. For numeric (in our example
Id and Age), the default is 0. For string (in our example Address and Name) or object, the
default value will be null (in this case nothing will be printed on the console) and for Boolean
(in our example IsPermanent), the default value is false.
Output:

In our example, we have not specified these default values. Then who provided these default
values and when? These default values are provided by the default constructor based on the
variable data type and the compiler will provide the default constructor at the time of
compilation. So, the Employee class will be converted as follows after compilation.

As you can see the Implicit Constructor which is always public and parameterless initialize
the variables with default values and these default values you are seeing in the output. As this
Implicit Constructor initializes the variables with default values, we also called this a System
Defined Default Constructor.
The constructor which is defined by the user without any parameter is called the user-
defined default constructor. This constructor does not accept any argument but as part of the
constructor body, you can write your own logic.
Example User-defined Default Constructor in C#
In the below example, within the Employee class, we have created a public parameterless
constructor which is used to initialize the variables with some default hard-coded values. And
then from the Main method, we created an instance of the Employee class and invoke the
Display method.
using System;
namespace ConstructorDemo
{
class Employee
{
public int Id, Age;
public string Address, Name;
public bool IsPermanent;
//User Defined Default Constructor
public Employee()
{
Id = 100;
Age = 30;
Address = "Bhubaneswar";
Name = "Anurag";
IsPermanent = true;
}
public void Display()
{
[Link]("Employee Id is: " + Id);
[Link]("Employee Age is: " + Age);
[Link]("Employee Address is: " + Address);
[Link]("Employee Name is: " + Name);
[Link]("Is Employee Permanent: " + IsPermanent);
}
}
class Program
{
static void Main(string[] args)
{
Employee e1 = new Employee();
[Link]();
[Link]();
}
}
}
Output:
The Employee class constructor is also called a Default Constructor because it is public and
parameter-less.

And more importantly, it does not matter


how many objects are being created for
the Employee class, each instance or
object is initialized with the same set of
values. This is the reason we call it a
Default Constrictor. As this constructor is
created by the user, so we call it a User-
Defined Default Constructor.
The drawback of the above user-defined
default constructor is that each and every
instance (i.e. object) of the class will be initialized (assigned) with the same set of values.
That means it is not possible to initialize each instance of the class with different values. For
a better understanding, please modify the Main method as follows and see the output.
class Program
{
static void Main(string[] args)
{
Employee e1 = new Employee();
[Link]();
Employee e2 = new Employee();
[Link]();
[Link]();
[Link]();
}
}
Output:

When should we define a parameterized constructor in a class?


If we want to initialize the object dynamically with the user-given values or if we want to
initialize each instance of a class with a different set of values then we need to use the
Parameterized Constructor in C#. The advantage is that we can initialize each instance
with different values.
What is Parameterized Constructor in C#?
If a constructor method is defined with parameters, we call it a Parameterized Constructor in
C#, and these constructors are defined by the programmers only but never can be defined
implicitly. So, in simple words, we can say that the developer-given constructor with
parameters is called Parameterized Constructor in C#.
Let us understand Parameterized Constructor in C# with Examples. Please have a look at the
below code. Here, we have a class called ParameterizedConstructor, and this class has one
constructor which is taking one integer parameter. As this constructor takes a parameter, we
call it a Parameterized Constructor. And in this constructor, we are printing the i value.
And now, when you are going to create an instance of the ParameterizedConstructor class, it
will ask you for the integer parameter value as shown in the below image.

Now, you can pass an integer value. Suppose, we pass the value 10, then that value 10 will
directly come to variable i which is then printed on the console. For a better understanding,
please have a look at the below image.

The complete example code is given below.


using System;
namespace ConstructorDemo
{
class Program
{
static void Main(string[] args)
{
ParameterizedConstructor obj = new ParameterizedConstructor(10);
[Link]();
}
}
public class ParameterizedConstructor
{
public ParameterizedConstructor(int i)
{
[Link]($"Parameterized Constructor is Called: {i}");
}
}
}
Output: Parameterized Constructor is Called: 10
So, in this way, we can create any number of instances of the class, and while creating the
instance we can pass different values and those values will go and sit in the variable i. In the
below example, we are creating two different instances of ParameterizedConstructor class
with two different values.
using System;
namespace ConstructorDemo
{
class Program
{
static void Main(string[] args)
{
ParameterizedConstructor obj1 = new ParameterizedConstructor(10);
ParameterizedConstructor obj2 = new ParameterizedConstructor(20);
[Link]();
}
}
public class ParameterizedConstructor
{
public ParameterizedConstructor(int i)
{
[Link]($"Parameterized Constructor is Called : {i}");
}
}
}
Output:

When should we use Parameterized Constructor in C#?


With the help of a Parameterized constructor, we can initialize each instance of the class with
a different set of values. That means using parameterized constructor we can store a different
set of values in different instances created in the class.
Now, let us call this Display method using two different instances. The complete example
code is given below.
using System;
namespace ConstructorDemo
{
class Program
{
static void Main(string[] args)
{
ParameterizedConstructor obj1 = new ParameterizedConstructor(10);
[Link]();
ParameterizedConstructor obj2 = new ParameterizedConstructor(20);
[Link]();
[Link]();
}
}
public class ParameterizedConstructor
{
int x;
public ParameterizedConstructor(int i)
{
[Link]($"Parameterized Constructor is Called : {i}");
}
public void Display()
{
[Link]($"Value of X = {x}");
}
}
}
Output:
As you can see in the above image, for both the instances it is printing the x value as 0. In
instance one we pass 10 to the constructor and in instance two we pass 20 to the constructor.
So, can we use the values 10 and 20 in place of x? Yes, it is possible. How it is possible? By
using Parameterized constructor only. Let us see how we can do this. Inside the constructor,
we can assign the x variable with the value of I as shown in the below image.

With the above changes in place, now if you run the application, then it will print 10 and 20
for the x variable. The complete example code is given below.
using System;
namespace ConstructorDemo
{
class Program
{
static void Main(string[] args)
{
ParameterizedConstructor obj1 = new ParameterizedConstructor(10);
[Link]();
ParameterizedConstructor obj2 = new ParameterizedConstructor(20);
[Link]();
[Link]();
}
}
public class ParameterizedConstructor
{
int x;
public ParameterizedConstructor(int i)
{
//Initializing the variable
x = i;
[Link]($"Parameterized Constructor is Called : {i}");
}
public void Display()
{
[Link]($"Value of X = {x}");
}
}
}
Output:
As we have created two instances separately i.e. obj1
and obj2. So, internally two copies of the x variable
are available in the memory for us. For a better
understanding, please have a look at the below
diagram. As you can see in the below image, we have
two separate objects i.e. obj1 and obj2. For obj1 we
have one copy of the x variable with the value 10 is
there and the obj2 another copy of the x variable with
the value 20 is there in the memory.

Copy Constructor in C#:


If we want to create multiple instances with the same values then we need to use the copy
constructor in C#, in a copy constructor the constructor takes the same class as a parameter to
it.
Let us understand Copy Constructor in C# with Examples. Please have a look at the below
code. This is the same code that we have written in our previous example.
using System;
namespace ConstructorDemo
{
class Program
{
static void Main(string[] args)
{
CopyConstructor obj1 = new CopyConstructor(10);
[Link]();
[Link]();
}
}
public class CopyConstructor
{
int x;
public CopyConstructor(int i)
{
x = i;
}
public void Display()
{
[Link]($"Value of X = {x}");
}
}
}
Output: Value of X = 10
Now, I want to create another instance with the same value. Then I can create another
instance as follows.

See, passing one


parameter is not a
difficult task. Suppose,
the constructor takes 10
or 20 parameters, then it
is a time-consuming and
error-prone process to
pass the same 10 or 20
parameters. We can
overcome this problem by using Copy Constructor in C#. The copy constructor takes a
parameter of the same class type. How we can pass a class name as a parameter. This is
because a class is a user-defined data type. For a better understanding, please have a look at
the below image.

With the above changes, now you


can see we have two constructors
as shown in the below image. One
constructor takes an int as a
parameter and the other
constructor takes the
CopyConstructor type as a
parameter.

So, can we define multiple constructors in a class? Yes, we can. Constructors can be
overloaded in C#. The complete example code is given below. Now, we are passing obj1 as a
parameter to the copy constructor.
using System;
namespace ConstructorDemo
{
class Program
{
static void Main(string[] args)
{
CopyConstructor obj1 = new CopyConstructor(10);
[Link]();
CopyConstructor obj2 = new CopyConstructor(obj1);
[Link]();
[Link]();
}
}
public class CopyConstructor
{
int x;
//Parameterized Constructor
public CopyConstructor(int i)
{
x = i;
}
//Copy Constructor
public CopyConstructor(CopyConstructor obj)
{
x = obj.x;
}
public void Display()
{
[Link]($"Value of X = {x}");
}
}
}
Now, if you run the application then you see that both the instances will have the same x
value as shown in the below image,

Now, the memory is separate for each instance but the value is going to be the same for both
instances. For a better understanding, please have a look at the below diagram.

How many Constructors can be Defined in a Class in C#?


In C#, within a class, we can define any number of constructors. But the most important point
that you need to remember is that each and every constructor must have a different signature.
A different signature means the number, type, and parameter order should be different. So, in
a class, we can define one no-argument constructor plus ‘n’ number of
parameterized constructors in C#.

Static Constructor
In C#, it is also possible to create a constructor as static and when we do so, it is called a
Static Constructor. If a constructor is declared explicitly by using the static modifier, then it is
called a static constructor in C#. All the constructors we defined till now are non-static or
instance constructors.
For a better understanding, please have a look at the below example. In a static constructor,
you cannot use any access specifiers like public, private, and protected.

But, when you will compile the above, the compiler will provide the default parameter less
constructor. For a better understanding, please have a look at the below code.

Inheritance
In C#, inheritance allows us to create a new class from an existing class. It is a key feature of
Object-Oriented Programming (OOP).
The class from which a new class is created is known as the base class (parent or superclass).
And, the new class is called derived class (child or subclass).
The derived class inherits the fields and methods of the base class. This helps with the code
reusability in C#.

How to perform inheritance?


In C#, we use the : symbol to perform inheritance.
For example,
class Animal {
// fields and methods
}

// Dog inherits from Animal


class Dog : Animal {
// fields and methods of Animal
// fields and methods of Dog
}
Here, we are inheriting the derived class Dog from the base class Animal. The Dog class can
now access the fields and methods of Animal class.
Example: C# Inheritance
using System;
namespace Inheritance {
// base class
class Animal {
public string name;
public void display() {
[Link]("I am an animal");
}

// derived class of Animal


class Dog : Animal {
public void getName() {
[Link]("My name is " + name);
}
}
class Program {
static void Main(string[] args) {
// object of derived class
Dog labrador = new Dog();
// access field and method of base class
[Link] = "Rohu";
[Link]();
// access method from own class
[Link]();
[Link]();
}
}
}
Output
I am an animal
My name is Rohu
In the above example, we have derived a subclass Dog from the superclass Animal. Notice
the statements,
[Link] = "Rohu";
[Link]();
Here, we are using labrador (object of Dog) to access the name and display() of
the Animal class. This is possible because the derived class inherits all fields and methods of
the base class.
Also, we have accessed the name field inside the method of the Dog class.

Is-a relationship
In C#, inheritance is an is-a relationship. We use inheritance only if there is an is-a
relationship between two classes.
For example,
Dog is an Animal
Apple is a Fruit
Car is a Vehicle
We can derive Dog from Animal class. Similarly, Apple from Fruit class
and Car from Vehicle class.

Protected Members in Inheritance


When we declare a field or method as protected, it can only be accessed from the same class
and its derived classes.
Example: protected Members in Inheritance
using System;
namespace Inheritance
{
// base class
class Animal {
protected void eat() {
[Link]("I can eat");
}

// derived class of Animal


class Dog : Animal {
static void Main(string[] args) {

Dog labrador = new Dog();

// access protected method from base class


[Link]();

[Link]();
}
}
}
Output
I can eat

Types of inheritance
There are the following types of inheritance:
1. Single Inheritance
In single inheritance, a single derived class inherits from a single base
class.
2. Multilevel Inheritance
In multilevel inheritance, a derived class inherits from a base and then the same derived class
acts as a base class for another class.

3. Hierarchical Inheritance
In hierarchical inheritance, multiple derived classes inherit
from a single base class.

4. Multiple Inheritance
In multiple inheritance, a single derived class inherits
from multiple base classes. C# doesn't support
multiple inheritance. However, we can achieve
multiple inheritance through interfaces.

5. Hybrid Inheritance
Hybrid inheritance is a combination of two or more types of
inheritance. The combination of multilevel and hierarchical
inheritance is an example of Hybrid inheritance.

Method Overriding
If the same method is present in both the base class and the derived class, the method
in the derived class overrides the method in the base class. This is called method overriding
in C#. For example,
using System;

namespace Inheritance {

// base class
class Animal {
public virtual void eat() {

[Link]("I eat food");


}

// derived class of Animal


class Dog : Animal {

// overriding method from Animal


public override void eat() {
[Link]("I eat Dog food");
}

}
class Program {

static void Main(string[] args) {


// object of derived class
Dog labrador = new Dog();

// accesses overridden method


[Link]();
}
}
}
Output
I eat Dog food
virtual - allows the method to be overridden by the derived class
override - indicates the method is overriding the method from the base class

C# Polymorphism
C# Polymorphism is a key concept in object-oriented programming (OOP) that allows
methods, properties, or operators to take multiple forms. The term "polymorphism" means
"many forms"; it enables a single interface to be used for different data types by improving
code flexibility and reusability. Polymorphism is achieved through method overloading and
method overriding, and it allows objects to be treated as instances of their base class. This
enhances maintainability and scalability in C# applications.
// C# Program to demonstrate the concept of Polymorphism
using System;
class Geeks
{
// method without any parameter
public void greet()
{
[Link]("Hello");
}

// method takes a single string parameter


public void greet(string name)
{
[Link]("Hello " + name);
}

static void Main(string[] args)


{
Geeks p1 = new Geeks();

// calls method without any argument


[Link]();

// calls method with an argument


[Link]("Geeks");

}
}

Output
Hello
Hello Geeks
Types of Polymorphism
Now that we understand the basics of polymorphism, let's explore its types in C#.
There are two types of polymorphism:
 Compile-time Polymorphism
 Runtime Polymorphism

Compile-time Polymorphism (Method Overloading)


Compile-time polymorphism, also called static polymorphism, is implemented using method
overloading. It allows a class to have multiple methods with the same name but different
signatures (parameter lists).
It can be differentiated, based perform:
 Changing the number of Parameters
 Changing data types of the parameters.
 Changing the Order of the parameters.
The return value alone is not sufficient for the compiler to figure out which function it
has to call. Method overloading is possible only when both methods have different parameter
types, resulting in distinct signatures.

1. Changing the number of Parameters


Method overloading can be achieved by varying the number of parameters in a method.
using System;

class Geeks
{
// Method takes two parameters
// Performs Multiplication
public static int Mathfunct(int a, int b)
{
return a * b;
}

// Method takes three parameters and


// Performs Addition
public static int Mathfunct(int a, int b, int c)
{
return a + b + c;
}

// Method takes four parameters and


// Performs Subtraction
public static int Mathfunct(int a, int b, int c, int d)
{
return a - b - c - d;
}

static void Main(string[] args)


{
int mult = Mathfunct(2, 3);
int add = Mathfunct(2, 3, 4);
int sub = Mathfunct(2, 3, 4, 5);

[Link]("Multiplication: " + mult);


[Link]("Addition: " + add);
[Link]("Subtraction: " + sub);
}
}

Output
Multiplication: 6
Addition: 9
Subtraction: -10
Explanation: In this example, we have three different methods with the same name
Mathfunct() but they perform differently and differentiate from each other by several
parameters passed in it and each method performs different operations.
2. Changing the Data types of the Parameters
Method overloading can be achieved by changing the data type of a method’s parameters.
// Overloading by changing the Data types
// of the parameters
using System;

class Geeks
{
// adding three integer values.
public static int Add(int a, int b, int c)
{
int sum = a + b + c;
return sum;
}

// adding three double values.


public static double Add(double a,
double b, double c)
{
double sum = a + b + c;
return sum;
}

public static void Main(String[] args)


{
[Link]("Add() with integer parameter");

int sum2 = Add(1,2,3);


[Link]("sum: " + sum2);

[Link]("Add() with double parameter");

double sum3 = Add(1.0, 2.0, 3.0);


[Link]("sum: " + sum3);
}
}

Output
Add() with integer parameter
sum: 6
Add() with double parameter
sum: 6

3. Changing the Order of the Parameters


If the method has the same name but a parameters order of parameters so in this way we can
also achieve the method overloading.
// Illustration of overloading by changing the
// Order of the parameters
using System;

class Geeks
{
public void Identity(String name, int id)
{
[Link]("Name1 : " + name + ", "
+ "Id1 : " + id);
}

public void Identity(int id, String name)


{
[Link]("Name2 : " + name + ", "
+ "Id2 : " + id);
}

public static void Main(String[] args)


{
Geeks obj = new Geeks();

// by changing the order


[Link]("Geek", 1);
[Link](2, "Geek2");
}
}

Output
Name1 : Geek, Id1 : 1
Name2 : Geek2, Id2 : 2

Compile-time Polymorphism (Operator Overloading)


Operator overloading gives the ability to use the same operator to do various
operations. It provides additional capabilities to C# operators when they are applied to user-
defined data types. It enables user-defined implementations of various operations where one
or both of the operands are of a user-defined class.
// C# program to illustrate the
// unary operator overloading
using System;
namespace Calculator
{

class Calculator
{

public int number1 , number2;


public Calculator(int num1 , int num2)
{
number1 = num1;
number2 = num2;
}

// Function to perform operation


// By changing sign of integers
public static Calculator operator -(Calculator c1)
{
c1.number1 = -c1.number1;
c1.number2 = -c1.number2;
return c1;
}

// Function to print the numbers


public void Print()
{
[Link] ("Number1 = " + number1);
[Link] ("Number2 = " + number2);
}
}

class EntryPoint
{
// Driver Code
static void Main(String []args)
{

// using overloaded - operator


// with the class object
Calculator calc = new Calculator(15, -25);

calc = -calc;

[Link]();
}
}
}

Output
Number1 = -15
Number2 = 25
Runtime Polymorphism (Method Overriding)
Runtime polymorphism, or dynamic polymorphism, is achieved by method
overriding. Method overriding occurs when a subclass provides a specific implementation for
a method that is already defined in the superclass or base class. The method in the subclass
must have the same signature as the method in the base class. By overriding a method, the
subclass can modify the behaviour of the inherited method. It allows a derived class to
provide a specific implementation of a method that is already defined in its base class.
 Virtual Method: The base class method must be declared as virtual to allow
overriding.
 Override Keyword: The derived class method must use the override keyword to
provide a new implementation.
using System;

namespace Geeks
{
// Base class
class Animal
{
// Virtual method to allow overriding
public virtual void MakeSound()
{
[Link]("Animal makes a sound");
}
}

// Derived class
class Dog : Animal
{
// Overriding the base class method
public override void MakeSound()
{
[Link]("Dog barks");
}
}

// Derived class
class Cat : Animal
{
// Overriding the base class method
public override void MakeSound()
{
[Link]("Cat meows");
}
}

class Program
{
static void Main(string[] args)
{
Animal myAnimal = new Animal();
Animal myDog = new Dog();
Animal myCat = new Cat();

[Link]();
[Link]();
[Link]();
}
}
}

Output
Animal makes a sound
Dog barks
Cat meows

Different Keywords used in Method Overriding


1. virtual Keyword
The virtual keyword is used in the base class to define a method that can be overridden in a
derived class.
using System;

class Animal
{
// Base class method marked as virtual
public virtual void Move()
{
[Link]("Animal is moving.");
}
}

class Dog : Animal


{
// Overriding the base class
// method using 'override'
public override void Move()
{
[Link]("Dog is running.");
}
}

// Main class
class Geeks
{
static void Main()
{
// Creating an object of the Dog class
Dog dog = new Dog();
[Link]();
}
}

Output
Dog is running.

2. override keyword
This keyword is used in the derived class to provide a specific implementation of a method
defined in the base class.
using System;

class Animal
{
// Base class method marked as virtual
public virtual void Move()
{
[Link]("Animal is moving.");
}
}

class Dog : Animal


{

// Overriding the base class


// method using 'override'
public override void Move()
{
[Link]("Dog is running.");
}
}

// Main class
class Geeks
{
static void Main()
{

// Creating an object of the Dog class


Dog dog = new Dog();
[Link]();
}
}

Output
Dog is running.

3. base Keyword
This method allows accessing methods, properties, or constructors of the base class from
within a derived class.
Use of Base Keyword:
Call methods or functions of base class from derived class.
Call the constructor internally of the base class at the time of inheritance.
using System;

class Animal
{
// Base class method marked as virtual
public virtual void Move()
{
[Link]("Animal is moving.");
}
}

class Dog : Animal


{

// Derived class method that calls


// the base class method using 'base'
public override void Move()
{
// Calls the Move() method
// from the Animal class
[Link]();
[Link]("Dog is running.");
}
}

// Main class
class Geeks
{
static void Main()
{
Dog dog = new Dog();
[Link]();
}
}

Output
Animal is moving.
Dog is running.
Method overriding is possible only in derived classes. A method is overridden in the derived
class when it is inherited from the base class.
 A non-virtual or static method cannot be overridden.
 Both the overridden method and the virtual method must have the same access level
modifie
 Use Case and Behavior of Polymorphism
 Allows methods to be written in a more general form, making code easier to extend
and maintain.
 Enhances the flexibility of the code and makes it easier to maintain.
 Enables the use of a uniform interface, which simplifies the design of systems that can
handle different data types and objects consistently.

C# Abstraction
Data Abstraction is the property by which only the essential details are shown to the user and
non-essential details or implementations are hidden from the user. In other words, Data
Abstraction may also be defined as the process of identifying only the required characteristics
of an object ignoring the irrelevant details. The properties and behaviours of an object
differentiate it from other objects of similar type and also help in classifying/grouping the
objects.
Example: Consider a real-life scenario of withdrawing money from an ATM. The user only
knows that in the ATM machine first enters the ATM card, then enters the PIN code of the
ATM card, and then enters the amount which the user wants to withdraw and at last, they get
their money. They don't know about the inner mechanism of the ATM or the implementation
of withdrawing money etc. The user just simply knows how to operate the ATM machine,
this is called abstraction.
1. Using Abstract Classes
An abstract class is declared with the help of an abstract keyword. In C# not allowed to create
objects of abstract class. We create a derived class take properties of the abstract class and
use them to achieve abstraction. Furthermore, we can access it from the Instance of the
derived class object. There are some important points to remember regarding abstract classes
mentioned below:
 We are not allowed to declare the abstract methods outside the abstract class.
 We can not define properties directly to the abstract method.
 The actual task or behaviour of the abstract method is implemented in the derived
class.
 We are not allowed to declare an abstract class as a Sealed Class
 We can not declare an abstract class as Static Class.

using System;

namespace DemoAbstraction
{

// abstract class
abstract class Shape
{

// abstract method
// No direct access
public abstract int area();
}

// square class inheriting


// the Shape class
class Square : Shape
{

// private data member


private int side;

// method of square class


public Square(int x = 0)
{
side = x;
}

// overriding of the abstract method of Shape


// class using the override keyword
public override int area()
{
[Link]("Area of Square: ");
return (side * side);
}
}

class Geeks
{
static void Main(string[] args)
{

// creating reference of Shape class


// which refer to Square class instance
Shape sh = new Square(4);

// calling the method


double result = [Link]();

[Link]("{0}", result);

}
}
}

Output
Area of Square: 16
2. Using Interfaces
The interface is declared using the interface keyword. We can create abstract methods inside
the interface similar to abstract classes and declare their functionality in the derived class.
From the derived class we can access those properties using the derived class by creating the
Instance of the derived class
using System;

// interface
public interface Student
{
//abstract method
void FavSub();
}

// Subclass for functionality


public class Geeky : Student
{
public void FavSub()
{
[Link]("My favorite subject is C#");
}
}
public class Geeks
{
public static void Main()
{
Student obj = new Geeky();

[Link]();
}
}

Output
My favorite subject is C#

Abstraction vs Encapsulation
Abstraction and encapsulation are the important features of OOPs. Their functionality is
similar and has slight differences which are shown below.
Features Abstraction Encapsulation

Definition Hiding the implementation and Encapsulate the data and


Features Abstraction Encapsulation

information in a single unit and


exposing the essential details
provide access through
only.
accessors.

Implements using abstract


Implemented using
classes and interface
access modifiers in C#
Implementation and properties

Used to hide the complex


Provide security and prevent
functionality and show the user-
unauthorized data access.
Purpose friendly Interface

A car class has different features


like drive(), break () and gear() Get () and set() accessors to
and we can use it without provide access controls on data.
Example knowing the implementation.

Advantages of Abstraction
It reduces the complexity of viewing things.
Avoids code duplication and increases reusability.
Helps to increase the security of an application or program as only important details are
provided to the user.

Indexers
In C#, an indexer allows an instance of a class or struct to be indexed as an array. When an
indexer is defined for a class, then that class will behave like a virtual array. Array access
operator i.e. ([ ]) is used to access the instance of the class which uses an indexer. A user can
retrieve or set the indexed value without pointing to an instance or a type member. The main
difference between Indexers and Properties is that the accessors of the indexers (get and set)
take parameters, whereas properties do not.
Syntax:
[Access_modifier] [Return_type] this [Parameter_list]
{
get
{ // get block code }
set
{// set block code }
}

In the above syntax,


Access_Modifier: Specifies accessibility (e.g., public, private, protected, or internal).
Return_Type: Specifies the data type of the value the indexer will return.
this: Keyword that refers to the current instance of the class.
Parameter_List: Specifies the parameters used to index the class.
get and set: Accessors used to retrieve and assign values.

// Use of Indexers in C#
using System;

class Geeks
{
private string[] values = new string[3];

// Indexer declaration
public string this[int index]
{
// Getter
get
{
return values[index];
}
// Setter
set
{
values[index] = value;
}
}
}

class Program
{
static void Main()
{
Geeks o = new Geeks();

// Assign values using the indexer


o[0] = "C";
o[1] = "C++";
o[2] = "C#";

// Access values using the indexer


[Link]("First value: " + o[0]);
[Link]("Second value: " + o[1]);
[Link]("Third value: " + o[2]);
}
}

Output
First value: C
Second value: C++
Third value: C#
Multiple-Index Parameters: Indexers can use multiple parameters for complex indexing,
enabling access to elements based on various criteria.
Indexer Overloading: Indexers can be overload like methods allows multiple indexers with
varying parameter types or counts to access elements in a class or struct.
Read-Only Indexers: Omitting the set accessor in an indexer makes it read-only, enabling
value retrieval while preventing modifications.
Implicit vs. Explicit Interface: Indexers can be implemented implicitly or explicitly when
defined as part of an interface. Implicit implementation is used when the indexer is defined
within the class itself, while explicit implementation is used when the indexer is implemented
explicitly to resolve any naming conflicts.
Indexers in Collections: Indexers are commonly used in collection classes, such
as dictionaries, lists, and [Link] access and manipulate elements within these collections
based on an index or key.
Custom Classes: Indexers can be implemented in custom classes to provide customized
access to class members based on an index. Allows for more intuitive and expressive
interaction with instances of the class.

// C# Multi-Parameter Indexer
using System;

public class Indexer


{
private int[] data = new int[10];

// Indexer with multiple parameters


public int this[int index, bool square]
{
get
{
if (square)
return data[index] * data[index];
else
return data[index];
}
set
{
if (square)
data[index] = (int)[Link](value);
else
data[index] = value;
}
}
// Overloaded indexer with string parameter
public int this[string n]
{
get
{
switch ([Link]())
{
case "first":
return data[0];
case "last":
return data[[Link] - 1];
default:
throw new
ArgumentException("Invalid index parameter.");
}
}
}

// Read-only indexer
public int this[int index]
{
get { return data[index]; }
}
}

public class Geeks


{
public static void Main()
{
Indexer i = new Indexer();

// Setting values using multiple parameter indexer


i[0, false] = 5;
i[1, false] = 10;
i[2, false] = 15;
i[3, false] = 20;

// Getting values using multiple parameter indexer


[Link](i[0, false]);
[Link](i[1, true]);

// Getting values using string parameter indexer


[Link](i["first"]);
[Link](i["last"]);

// Getting values using read-only indexer


[Link](i[2]);
}
}

Output
5
100
5
0
15

Common questions

Powered by AI

In C#, polymorphism is facilitated through the use of the 'virtual' keyword in a base class method to allow it to be overridden, and the 'override' keyword in a derived class to provide a specific implementation. This enables objects to be treated as instances of their base class while using the methods of their derived class, thus supporting polymorphism's concept of 'many forms' .

Method overloading involves defining multiple methods in the same class with the same name but different parameters, enabling different operations based on supplied arguments. Conversely, method overriding requires matching method signatures between a base and derived class, altering behavior in the derived class. Overloading is static/compile-time polymorphism; overriding is dynamic/runtime polymorphism. An example: overloading 'greet' with different parameters, while overriding 'eat' alters base class behavior in a derived class .

C# does not support multiple inheritance directly due to the complexity and potential issues such as the diamond problem it introduces. However, multiple inheritance can be achieved in C# through the use of interfaces, which allow a class to implement multiple interface contracts without inheriting multiple class functionalities simultaneously .

A parameterized constructor in C# is defined with parameters, allowing for dynamic initialization of objects with user-given values. This enables each instance of a class to be initialized with different values, unlike a default constructor, which initializes objects with predefined settings typically set by the language or developer .

Method overriding in C# allows a derived class to provide a specific implementation for a method that is already defined in its base class. The method in the base class must be declared with the 'virtual' keyword, and the derived class method must use the 'override' keyword, ensuring the subclass method has the same signature and modifies the behavior of the inherited method .

The 'base' keyword in C# is used within derived classes to call methods, properties, or constructors of a base class. In method overriding, it allows the derived class to access the original implementation of a base class method, ensuring that the new method provides additional or modified functionality over the base method while maintaining continuity and specific access control .

A copy constructor in C# is used to create a new instance of a class using another instance, copying the values of the fields from one object to another. This differs from a parameterized constructor, which initializes an instance with specified values provided by the developer at the time of instantiation, not based on another existing instance .

Encapsulation in object-oriented programming is the concept of restricting access to certain components of an object to protect the internal state and integrity of the object. In C#, access modifiers like 'protected' limit access to methods and fields to the class itself and any derived classes, promoting encapsulation by controlling how internal components are exposed and used, which enhances security and reduces the risk of unintended interference .

A programmer should use the 'protected' access modifier when there is a need to allow class methods to be accessible only within the class itself and by derived classes. This is useful when specific methods should be hidden from outside access to maintain internal integrity while still being available for overridden functionality in subclasses .

Polymorphism enhances code maintainability and scalability in C# by allowing a single interface to accommodate different data types and behaviors, which means changes to the system can be made with minimal impact on existing code. It permits developers to introduce new functionality, override existing ones, and interchangeably use derived and base class objects, promoting reusable and extendable code structures .

You might also like