0% found this document useful (0 votes)
5 views63 pages

Oops in C#

.NET Framework is a software development platform created by Microsoft that allows developers to build a variety of applications, including web, mobile, and desktop applications. It consists of two main components: the Common Language Runtime (CLR) for executing applications and the Base Class Library (BCL) for providing essential functionalities. The framework supports multiple programming languages and is available in different versions, including the original .NET Framework, the cross-platform .NET, and Xamarin/Mono for mobile applications.
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)
5 views63 pages

Oops in C#

.NET Framework is a software development platform created by Microsoft that allows developers to build a variety of applications, including web, mobile, and desktop applications. It consists of two main components: the Common Language Runtime (CLR) for executing applications and the Base Class Library (BCL) for providing essential functionalities. The framework supports multiple programming languages and is available in different versions, including the original .NET Framework, the cross-platform .NET, and Xamarin/Mono for mobile applications.
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
You are on page 1/ 63

Introduction to .

NET Framework
Here, I am going to give you an overview of the DOT NET Framework. This is important for
you as a dot net developer to know the history and evolution of the DOT NET Framework.
Here, in this session, first, we will discuss what was there before the .NET Framework and
what problems we face in that, and how we overcome all those problems in the .NET
Framework. Before DOT NET Framework COM is there. So, let us first discuss what is COM
and what problems we face in COM.

What is COM?
COM stands for Component Object Model. The COM is one of the Microsoft Frameworks.
Using this Framework, we can develop Windows Applications (Desktop or Standalone
Applications for Windows OS) as well as Web Applications. In earlier COM, VB is the
programming language that is used to implement Windows applications and ASP is the
technology used to implement web applications.
What are the disadvantages of COM?
There are two major disadvantages of the COM Framework. They are as follows:
1. Incomplete Object-Oriented Programming means it will not support all the features
of OOPs.
2. Platform Dependent means COM applications can run on only Windows OS.

To overcome the above problems, Microsoft introduces .NET Framework.

What does .NET Represent?


NET stands for Network Enabled Technology (Internet). In .NET, dot (.) refers
to Object-Oriented, and NET refers to the internet. So, the complete .NET means
through Object-Oriented we can implement internet-based applications.
According to Microsoft, .NET is a Free, Cross-Platform, Open-Source developer
platform for building many different types of applications. With .NET, we can use
multiple languages (C#, VB, F#, etc.), Editors (Visual Studio, Visual Studio Code,
Visual Studio for Mac, OmniSharp, JetBrains Rider, etc), and Libraries to build for
Web, Mobile, Desktop, Games, IoT, and more.
Cross Platform: Whether you are working in C#, F#, or Visual Basic, your code will
run on any compatible operating system. You can build many types of apps
with .NET. Some are Cross-Platform, and some target a specific set of operating
systems and devices.
Libraries: To extend functionality, Microsoft and others maintain a healthy .NET package
ecosystem. NuGet is a package manager built specifically for .NET that contains over 100,000
packages.
What is a Framework?
A framework is a software. Or you can say a framework is a collection of many small
technologies integrated together to develop applications that can be executed anywhere.
What does the .NET Framework Provide?
The DOT NET Framework provides two things as follows
1. BCL (Base Class Libraries)
2. CLR (Common Language Runtime)
What is BCL?
Base Class Libraries (BCL) are designed by Microsoft. Without BCL we can’t write any code
in .NET. So, BCL is also known as the basic building block of .NET Programs. These are
installed into the machine when we installed the .NET framework. BCL contains pre-defined
classes and these classes are used for the purpose of application development.
What is CLR?
CLR stands for Common Language Runtime and it is the core component
under the .NET framework which is responsible for converting the MSIL (Microsoft
Intermediate Language) code into native code. In our CLR session, we will discuss CLR in
detail.

In the .NET framework, the code is compiled twice.


1. In the 1st compilation, the source code is compiled by the respective language
compiler and generates the intermediate code which is known as MSIL (Microsoft
Intermediate Language) or IL (Intermediate language code), or Managed Code.
2. In the 2nd compilation, MSIL is converted into Native code (native code means code
specific to the Operating system so that the code is executed by the Operating
System) and this is done by CLR.
Always 1st compilation is slow and 2nd compilation is fast.
What is JIT?
JIT stands for the Just-in-Time compiler. It is the component of CLR that is
responsible for converting MSIL code into Native Code. Native code is code that is
directly understandable by the operating system.
Different types of .NET Framework
The .NET framework is available in three different flavors
1. .NET Framework: .NET Framework is the original implementation of .NET. It supports
running websites, services, desktop applications, and more on Windows OS Only.
2. .NET: .NET is a cross-platform implementation for running websites, services, and
console applications on Windows, Linux, and macOS. .NET is open source on GitHub
and .NET was previously called .NET Core.
3. Xamarin/Mono: Xamarin/Mono is a .NET implementation for running apps on all the
major mobile operating systems, including iOS and Android.
Note: .NET Framework is Platform-Dependent while .NET or .NET Core is Platform
Independent. Here, we are not talking about Web Applications. Web Applications are
independent of Operating Systems.
What is not .NET?
1. .NET is not an Operating system.
2. .NET is not a database
3. It is not an ERP application.
4. .NET is not a Testing Tool.
5. It is not a programming language.
What is Exactly .NET?
.NET is a framework tool that supports many programming languages and many
technologies. .NET support 60+ programming languages. Of 60+ programming
languages, 9 are designed by Microsoft and the remaining are designed by non-
Microsoft. Microsoft-designed programming languages are as follows:
1. VB.NET
2. C#.NET
3. VC++.NET
4. J#.NET
5. F#.NET
6. Jscript.NET
7. WindowsPowerShell
8. Iron phyton
9. Iron Ruby
Technologies supported by the .NET framework are as follows
1. ASP.NET (Active Server Pages.NET) – MVC, Web API, Core MVC, Core Web API, Core
Blazor, etc.
2. ADO.NET (Active Data Object.NET)
3. WCF (Windows Communication Foundation)
4. WPF (Windows Presentation Foundation)
5. WWF (Windows Workflow Foundation)
6. AJAX (Asynchronous JavaScript and XML)
7. LINQ (Language Integrated Query)
8. Entity Framework
What are a Language and its need?
1. Language acts as the mediator between the programmer and the system.
2. It offers some rules and regulations for writing the program.
3. The language also offers some libraries which are required for writing the program.
What are Technology and its Needs?
Technology is always designed for a particular purpose. For example, the development
of web-related applications in .NET using the technology ASP.NET. But the technology
does not offer any specific rules for writing the programs. That’s why technology can’t be
implemented individually. VB.NET, C#.NET, and F#.NET are programming languages.
Using any of these languages we can implement windows/desktop applications
individually. Every language is having its own compiler
.NET Framework Architecture and Components
In this article, I am going to discuss .NET Framework Architecture and Components in detail.
Please read our previous article where we give a brief introduction to .NET Framework. At
the end of this article, you will understand what is .NET Framework, .Net Framework
Architecture, .NET Components, and .NET Framework Design Principle are.
.Net Framework Architecture
The two major components of the .NET Framework are the Common Language Runtime and
the .NET Framework Class Library.
1. CLR: The Common Language Runtime (CLR) is the execution engine that handles
running applications. It provides services like thread management, garbage
collection, type safety, exception handling, and more.
2. BCL: The Base Class Library provides a set of APIs and types for common
functionality. It provides types for strings, dates, numbers, etc. The Class Library
includes APIs for reading and writing files, connecting to databases, drawing, and
more.
The .NET applications are written in C#, F#, or VB programming languages. The Source Code
is compiled into an intermediate language code called IL or MSIL or CIL (Common
Intermediate Language). And the Compiled code is stored in assemblies with .DLL or .EXE file
extension.
When an application runs, the CLR takes the Assembly (IL Code or MSIL Code, or CIL) and
uses the Just-in-Time compiler (JIT) to convert the MSIL or IL code into machine code that
can execute on the specific architecture of the computer it is running on.
What is .NET Framework used for?
.NET Framework is used to create and run software applications. .NET apps can run on many
operating systems, using different implementations of .NET (.NET Framework, .NET Core
or .NET, and Xamarin/Mono). The .NET Framework is used for running .NET apps on
Windows, The .NET Core or .NET is used for running .NET Apps on Windows, Linux, and
macOS. And Xamarin/Mono is used for running apps on all the major mobile operating
systems, including iOS and Android.
Who uses .NET Framework?
Software developers and the users of their applications both use .NET Framework:
1. Users of applications built with the .NET Framework need to have .NET Framework
installed. In most cases, .NET Framework is already installed with Windows. If
needed, you can download .NET Framework.
2. Software developers use .NET Framework to build many different types of
applications such as websites, services, desktop apps, and more with Visual Studio.
Visual Studio is an integrated development environment (IDE) that provides
development productivity tools and debugging capabilities.
Why do I need .NET Framework?
You need .NET Framework installed on your machine to run applications on Windows that
were created using .NET Framework. It is already included in many versions of Windows. You
only need to download and install .NET Framework if prompted to do so.
How does .NET Framework work?
.NET Framework applications are developed using C#, F#, or VB Programming Language and
compiled into Common Intermediate Language (CIL) or MSIL (Microsoft Intermediate
Language). The Common Language Runtime (CLR) runs .NET applications on a given
machine, converting the CIL code or MSIL code to machine code that the corresponding
machine can execute.
What are the main Components/Features of the .NET Framework?
The two major components of the .NET Framework are the Common Language Runtime
(CLR) and the .NET Framework Class Library. The CLR is the execution engine that handles
running applications. The Base Class Library provides a set of APIs and types for common
functionality.
What is the difference between .NET and .NET Framework?
.NET and .NET Framework share many of the same components and you can share code
across the two. Some of the key differences between them are as follows:
1. .NET is Cross-Platform and runs on Linux, macOS, and Windows OS. .NET
Framework only runs on Windows OS.
2. .NET is Open-Source and accepts contributions from the community. The .NET
Framework source code is available but does not take direct contributions.
3. .NET Framework is included in Windows and automatically updated machine-wide
by Windows Update. .NET is shipped independently.
Applications Developed using .NET Framework
The types of applications that can be built in the .Net framework are classified broadly into
the following categories.
WinForms – This is used for developing Forms-based applications, which would run on an
end-user machine. Notepad is an example of a client-based application. Windows Forms is a
smart client technology for the .NET Framework, a set of managed libraries that simplify
common application tasks such as reading and writing to the file system.
ASP.NET – This is used for developing web-based applications, which are made to run on any
browser such as Edge, Chrome or Firefox. ASP.NET is a web framework designed and
developed by Microsoft. It is used to develop websites, web applications, and web services.
It provides a fantastic integration of HTML, CSS, and JavaScript. It was first released in
January 2002.
1. The Web application would be processed on a server, which would have Internet
Information Services Installed.
2. Internet Information Services or IIS is a Microsoft component that is used to execute
an ASP.NET application.
3. The result of the execution is then sent to the client machines, and the output is
shown in the browser.
ADO.NET: This technology is used to develop applications to interact with databases
such as Oracle or Microsoft SQL Server. ADO.NET is a module of the .Net
Framework, which is used to establish a connection between applications and data
sources. Data sources can be such as SQL Server and XML. ADO .NET consists of
classes that can be used to connect, retrieve, insert, and delete data.
WCF (Windows Communication Foundation): It is a framework for building
service-oriented applications. Using WCF, you can send data as asynchronous
messages from one service endpoint to another.

LINQ (Language Integrated Query): It is a query language, introduced in .NET 3.5


framework. It is used to make the query for data sources with C# or Visual Basics
programming languages.
Entity Framework: It is an ORM-based open-source framework that is used to work
with a database using .NET objects. It eliminates a lot of developers’ effort to handle
the database. It is Microsoft’s recommended technology to deal with the database.

Parallel LINQ: Parallel LINQ or PLINQ is a parallel implementation of LINQ to


objects. It combines the simplicity and readability of LINQ and provides the power of
parallel programming. It can improve and provide fast speed to execute the LINQ
query by using all available computer capabilities.
Introduction to C# Programming Language

Why did C#.NET come to the market?


C#.NET Programming Language is mainly designed to overcome the disadvantages of C and C++ and
to develop internet applications (web applications) by achieving platform independence.
Why C# is so much popular nowadays?
C#.NET is so much popular nowadays because of the following reasons.
C# is Simple and Familiar:
C# is simple because C# simplifies the programmer’s job by avoiding certain features of C and C++. C#
avoids explicit memory management. Memory management in C# is automatic. It is done by CLR. So,
there is no chance of memory leakage. There is a pointer concept in C# but it is restricted. C# is very
familiar to programmers because it is modeled on the C and C++ languages. C# uses many features of
C and C++; therefore, C# codes look like C and C++ codes. We can say C# is the simplified version of C
and C++.
C# is Portable:
Portability allows the programmer to write the same code for different machines (operating
systems). C# provides portability in two ways
1. Source Code Portability
2. IL Code Portability (DLL and EXE)
In C#, we can write the source code in Multiple OS and get the output. Even though we can IL Code
Portability is also available. So, once you have the DLL and EXE, then you can use those DLLs and EXEs
on different OS and you can get the output as expected. Whereas in the case of C and C++ there is
only source code portability.
C# is Architecturally Neutral:
The behavior of C# programs doesn’t change when we move from one system to another which
means it will provide the same output in every machine because in C# memory layout decisions are
not made at compile time, it is made at run time by CLR. It is because of CTS (Common Type System)
and in our coming session we will discuss it in detail. But in the case of C and C++ programs, the
behavior changes when we move the program from one system to another and the reason for this is
the size of data types varies from OS to OS.
C# is Secured:
C# is secured because the C# programs are executed in a secured environment called CLR. CLR will
provide security to the C# programs.
C# is Robust:
Robust means Strong. C# is a strong type-checking language having strict type-checking during both
compilation time and execution time which allows us to develop error-free applications and
programs.
C# is Distributed:
Using C# Programming Language, we can develop distributed applications whose resources are
shared by more than one client. An application or program whose resources are shared by more than
one client is called a distributed application. As C# is used for developing such applications for
example WCF Applications, Restful Services, etc. So, C# is a distributed programming language.
C# is Multithreaded:
A process is divided into several small parts known as threads or lightweight processes. Sending
multiple threads to the processor for processing is known as multithreading. Multi-threading means
handling multiple tasks simultaneously. For example, we can listen to music while scrolling a page
and at the same time we can download an application from the internet on a computer.
If multiple threads are used to execute your application code, then it is called Multithreading.
Multithreading is a mechanism to implement Concurrent Programming where multiple threads
execute the code simultaneously. And using C# Programming language we can develop multithread
applications. So, C# supports multithreaded programming.
C# is Dynamic:
C# 4.0 introduced a new type called dynamic that avoids compile-time type checking. A dynamic type
escapes type checking at compile-time; instead, it resolves the type at run time. So, if you don’t
know the type of data that you want to store, then you can use dynamic as the data type, and at
runtime based on value or data, the type will automatically resolve. So, C# is dynamic.
C# is Compiled and Interpreted:
We know a programming language is either compiled or interpreted. But C# combines both
approaches. That’s why C# is called a two-stage system.
First C# compiler CSC translates source code into an intermediate language code known as MSIL
(Microsoft Intermediate Language) or CIL (Common Intermediate Language) code. But these MSIL or
CIL or IL codes are not machine instructions. So, in the second stage, these MSIL or CIL, or IL codes
are interpreted by the C# interpreter (One Component of CLR called JIT- Just in Time Compiler). As a
result, machine instructions will be generated which are directly executed by the machine. Hence,
we are saying C# is both interpreted and compiled language.
C# is Object-Oriented:
Except for the primitive data types, all elements in C# are objects. Object-oriented is not a
programming language, it is a programming technique or concept, or principle which defines a set of
rules and regulations for organizing the data and instructions. The concepts provided by oops are as
follows
1. Encapsulation
2. Abstraction
3. Polymorphism
4. Inheritance
The Programming Language which supports these four features is known as an Object-Oriented
Programming Language. And C# Programming Language supports these four features, so C# is
Object-Oriented.
C# is Platform Independent:
Many Programming Languages are compatible with only one platform. Now, with the introduction
of .NET Core or .NET, C# was specifically designed to be platform-independent. C# applications
with .NET Core or .NET can be run on Windows, Linux, and Mac operating systems. So, we can say C#
is Platform Independent with .NET Core or .NET.
Automatic Memory Management:
The .NET Framework automatically manages memory allocation and de-allocation for objects. When
a dot net application runs, lots of objects are created. At a given point in time, it is possible that
some of those objects are not used by the application. Garbage Collector in .NET Framework is
nothing but a Small Routine or you can say it is a Background Process that runs periodically and try to
identify what objects are not being used currently by the application and de-allocates the memory of
those objects. So, as a developer, we need not worry about how memory allocation and deallocation
are done in .NET Applications.
Exception Handling:
C# Provides Strong Exception Handling Features which can be used to stop the Abnormal Termination
of the program and you can also provide user-understandable messages when an exception is raised.
C# Definition based on the above features:
C# is just a Simple, Secure, Robust, Portable, Platform-Independent, Architectural Neutral,
Multithreaded, Automatic Memory Management, Object-Oriented Programming Language with a
strong type Exception Handling mechanism for developing different kinds of applications such as
Web, Windows Form, Console, Web Services, Mobile Apps, etc. which can be run on different
Operating Systems such as Windows, Linus, and Mac.
Features of C#
Although C# constructs closely follow traditional high-level languages, C and C++ and being an
object-oriented programming languages. It has a strong resemblance with Java, it has numerous
strong programming features that make it endearing to a number of programmers worldwide.
Following is the list of a few important features of C# −
1. Simple: C# is a simple language in the sense that it provides a structured approach (to break
the problem into parts), a rich set of library functions, data types, etc.
2. Modern Programming Language: C# programming is based upon the current trend and it is
very powerful and simple for building scalable, interoperable, and robust applications.
3. Object-Oriented: C# is an object-oriented programming language. OOPs makes development
and maintenance easier whereas in Procedure-oriented programming language it is not easy
to manage if code grows as the project size grows.
4. Type-Safe: C# type safe code can only access the memory location that it has permission to
execute. Therefore, it improves the security of the program.
5. Interoperability: The interoperability process enables the C# programs to do almost anything
that a native C++ application can do.
6. Scalable and Updateable: C# is an automatic scalable and updateable programming
language. For updating our application, we delete the old files and update them with new
ones.
7. Component Oriented: C# is a component-oriented programming language. It is the
predominant software development methodology used to develop more robust and highly
scalable applications.
8. Structured Programming Language: C# is a structured programming language in the sense
that we can break the program into parts using functions. So, it is easy to understand and
modify.
9. Rich Library: C# provides a lot of inbuilt functions that make development fast.
10. Fast Speed: The compilation and execution time of the C# language is fast.
Types of Applications Developed using C#:
With the help of the C# programming language, we can develop different types of secured and
robust applications:
1. Window applications
2. Web applications
3. Distributed applications
4. Web service applications
5. Database applications
6. Mobile Applications, etc

Object-Oriented Programming (OOPs) in C#


1. Introduction
 OOP is a programming paradigm that focuses on representing problems as collections of
interacting objects.
 It provides a structured approach to software development, emphasizing reusability,
maintainability, and flexibility.
 Key principles of OOP:
o Encapsulation: Bundling data (attributes) and methods (behaviors) that operate on
that data within a single unit (class).
o Inheritance: Creating new classes (derived/child classes) from existing ones
(base/parent classes), inheriting their properties and methods.
o Polymorphism: The ability of objects to take on many forms. It allows objects of
different classes to be treated as objects of a common 1 type.
o Abstraction: Hiding complex implementation details and exposing only the essential
features of an object.
2. Problems with Functional Programming
 Reusability: Difficult to reuse code across different parts of the application.
 Extensibility: Difficult to add new features or modify existing functionality without significant
code changes.
 Maintainability: Code becomes complex and difficult to understand and modify as the
application grows.
 Simplicity: Lack of modularity can lead to scattered code and increased complexity.
3. How OOP Addresses Functional Programming Problems
 Reusability: Achieved through inheritance and class-based design.
 Extensibility: Inheritance and polymorphism enable easy extension of existing classes.
 Maintainability: Encapsulation and modularity improve code organization and readability.
 Simplicity: Abstraction hides complexity, making the code easier to understand and use.
4. Key Concepts
 Class: A blueprint or template for creating objects. It defines the properties (data members)
and methods (member functions) that objects of that class will have.
 Object: An instance of a class. It represents a real-world entity with specific values for its
properties.
5. OOP Principles in Detail
 Encapsulation
o Definition: Bundling data and methods that operate on that data within a single unit
(class).
o Benefits:
 Protects data integrity by controlling access to internal state.
 Improves code maintainability and reduces the risk of unintended side
effects.
o Implementation:
 Use access modifiers (public, private, protected, internal) to control the
accessibility of class members.
 Inheritance
o Definition: Creating new classes (derived classes) from existing classes (base classes).
o Benefits:
 Promotes code reusability.
 Enables creation of hierarchical relationships between classes.
 Facilitates code extensibility.
o Types:
 Single Inheritance: A class inherits from only one base class.
 Multiple Inheritance: A class inherits from multiple base classes (not directly
supported in C#, but can be achieved using interfaces).
o Implementation:
 Use the : (colon) operator to inherit from a base class.
 Polymorphism
o Definition: The ability of objects to take on many forms.
o Types:
 Static Polymorphism (Compile-time Polymorphism):
 Achieved through method overloading (same method name,
different parameters).
 Dynamic Polymorphism (Runtime Polymorphism):
 Achieved through method overriding (same method signature in
derived class).
o Benefits:
 Increases code flexibility and adaptability.
 Enables writing more generic and reusable code.
 Abstraction
o Definition: Hiding complex implementation details and exposing only the essential
features of an object.
o Benefits:
 Simplifies the interface for users of the class.
 Reduces complexity and improves code readability.
o Implementation:
 Using abstract classes and interfaces.
6. Advantages of OOP in C#
 Modularity: Encapsulation promotes modularity, making code easier to manage and
maintain.
 Reusability: Inheritance and polymorphism enable code reuse, reducing development time
and effort.
 Flexibility: Polymorphism allows for more flexible and adaptable code.
 Maintainability: Encapsulation and modularity improve code maintainability.
 Scalability: OOP principles help create scalable and extensible software systems.
 Readability: OOP promotes code that is more human-readable and self-explanatory.
7. Real-world Applications of OOP
 Game development: Creating game objects (characters, items, etc.)
 Graphical User Interfaces (GUIs): Designing interactive user interfaces with classes and
objects.
 Web development: Building web applications with object-oriented frameworks like ASP.NET
MVC.
 Database applications: Creating object-relational databases (ORMs) to interact with
databases.
 Business applications: Modeling real-world business entities (customers, products, orders,
etc.)
Classes and Objects in C#
1. Introduction
 Class: A blueprint or template that defines the properties (data members) and methods
(member functions) that objects of that class will have.
 Object: An instance of a class. It represents a real-world entity with specific values for its
properties.
2. Class and Objects from Layman's Perspective
 Class: A classification or grouping of objects with similar characteristics. For example, the
class "Car" encompasses all cars, regardless of their specific make or model.
 Object: An individual instance of a class. A specific car (e.g., a red Toyota Camry) is an object
of the class "Car."
3. Class and Objects from Programming Perspective
 Class: A user-defined data type that encapsulates data (properties) and methods (functions)
that operate on that data.
 Object: An instance of a class. It has its own set of property values and can perform the
actions defined by the class's methods.
4. Creating a Class and Object in C#
 Class Definition:
C#
public class MyClass
{
// Properties
public int Id { get; set; }
public string Name { get; set; }

// Methods
public void Display()
{
Console.WriteLine($"Id: {Id}, Name: {Name}");
}
}
 Object Creation:
C#
MyClass obj1 = new MyClass();
obj1.Id = 1;
obj1.Name = "John Doe";
obj1.Display();

MyClass obj2 = new MyClass();


obj2.Id = 2;
obj2.Name = "Jane Doe";
obj2.Display();
5. Difference between Class and Objects
Feature Class Object
Definition Blueprint/Template Instance of a class
Representation Abstract Concrete
Properties Defines properties Holds specific values for properties
Methods Defines methods Can execute methods
Relationship One class can create many objects An object belongs to only one class
Export to Sheets
6. Types of Classes in C#
 Abstract Class:
o Cannot be instantiated directly.
o Can contain abstract methods (methods without implementation).
o Used as a base class for other classes.
o Example:
C#
public abstract class Shape
{
public abstract double CalculateArea();
}
 Concrete Class:
o Can be instantiated directly.
o Contains concrete implementations for all methods.
o Example:
C#
public class Circle : Shape
{
public double Radius { get; set; }

public override double CalculateArea()


{
return Math.PI * Radius * Radius;
}
}
 Sealed Class:
o Cannot be inherited from.
o Used to prevent unintended inheritance.
o Example:
C#
public sealed class MySealedClass
{
// ...
}
 Partial Class:
o A class that is divided into multiple parts across different files.
o Useful for organizing large classes into smaller, more manageable units.
o Example:
C#
// Part 1
public partial class MyClass
{
// ...
}

// Part 2
public partial class MyClass
{
// ...
}
 Static Class:
o Contains only static members (methods and fields).
o Cannot be instantiated.
o Used for utility methods and constants.
o Example:
C#
public static class MathUtils
{
public static double PI = 3.14159;
public static int Add(int a, int b)
{
return a + b;
}
}
7. Key Points
 Classes and objects are fundamental concepts in object-oriented programming.
 Understanding the relationship between classes and objects is essential for effective C#
programming.
 Different types of classes offer varying levels of flexibility and control.
Constructors in C#
1. Introduction
 A constructor is a special method within a class that is automatically called when an object of
that class is created.
 Its primary purpose is to initialize the object's state (properties/fields).
2. Key Characteristics
 Name: The constructor's name must be the same as the class name.
 Return Type: Constructors do not have a return type, not even void.
 Purpose:
o Initialize the object's properties.
o Allocate necessary resources.
 Types:
o Default Constructor (Parameterless):
 A constructor that takes no arguments.
 The compiler provides a default constructor if no other constructors are
defined in the class.
o Parameterized Constructor:
 A constructor that accepts arguments.
 Allows for flexible object initialization with different values.
3. Implicit Constructor
 The compiler automatically generates a default constructor (parameterless) if no other
constructors are defined explicitly in the class.
 This implicit constructor initializes the fields of the class with their default values (e.g., 0 for
integers, null for strings).
4. Explicit Constructor
 A constructor that is defined explicitly by the programmer.
 Can be parameterless or parameterized.
 Allows for custom initialization logic.
5. Example: Implicit Constructor
C#
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}

// The compiler generates an implicit default constructor:


// public Employee()
// {
// Id = 0;
// Name = null;
// }
6. Example: Explicit Parameterless Constructor
C#
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }

public Employee()
{
Console.WriteLine("Default Constructor Called");
}
}
7. Example: Explicit Parameterized Constructor
C#
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }

public Employee(int id, string name)


{
Id = id;
Name = name;
}
}
8. Constructor Overloading
 A class can have multiple constructors with different signatures (different number or types of
parameters).
 Example:
C#
public class Employee
{
public Employee() { } // Default constructor
public Employee(int id) { Id = id; }
public Employee(int id, string name)
{
Id = id;
Name = name;
}
}
9. Important Points
 Constructors cannot have a return type, not even void.
 Constructors cannot be inherited.
 A class can have only one constructor with no parameters.
 11. Code Example
 C#
 using System;

 public class Program
 {
 public static void Main(string[] args)
 {
 // Create objects using different constructors
 Employee employee1 = new Employee();
 Employee employee2 = new Employee(1);
 Employee employee3 = new Employee(2, "John Doe");

 // Access and display employee information
 Console.WriteLine(employee1.Id); // Output: 0
 Console.WriteLine(employee2.Id); // Output: 1
 Console.WriteLine(employee3.Id); // Output: 2
 Console.WriteLine(employee3.Name); // Output: John Doe

 Console.ReadLine();
 }
 }

 public class Employee
 {
 public int Id { get; set; }
 public string Name { get; set; }

 public Employee() { }
 public Employee(int id) { Id = id; }
 public Employee(int id, string name)
 {
 Id = id;
 Name = name;
 }
 }
 12. Conclusion
 Constructors are essential for object initialization in C#. They provide a mechanism to
control how objects are created and ensure that they are properly initialized with
appropriate values. By understanding and effectively using constructors, you can
write more robust and maintainable C# code.

Constructors in C#
1. Introduction
 A constructor is a special method within a class that is automatically called whenever
an object of that class is created.
 Its primary purpose is to initialize the object's state (properties/fields) with appropriate
values.
2. Key Characteristics
 Name: The constructor's name must be the same as the class name.
 Return Type: Constructors do not have a return type, not even void.
 Purpose:
o Initialize the object's properties.
o Allocate necessary resources.
o Perform custom logic at object creation.
 Types:
o Default Constructor (Parameterless):
 A constructor that takes no arguments.
 The compiler provides a default constructor if no other constructors are
defined in the class. It initializes fields with their default values (e.g., 0
for integers, null for strings).
o Parameterized Constructor:
 A constructor that accepts arguments.
 Allows for flexible object initialization with different values.
3. Implicit Constructor
 The compiler automatically generates a default constructor (parameterless) if no other
constructors are defined explicitly in the class.
4. Explicit Constructor
 A constructor that is defined explicitly by the programmer.
 Can be parameterless or parameterized.
 Allows for custom initialization logic.
5. Example: Implicit Constructor
C#
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}

// The compiler generates an implicit default constructor:


// public Employee()
// {
// Id = 0;
// Name = null;
// }
6. Example: Explicit Parameterless Constructor
C#
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }

public Employee()
{
Console.WriteLine("Default Constructor Called");
}
}
7. Example: Explicit Parameterized Constructor
C#
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }

public Employee(int id, string name)


{
Id = id;
Name = name;
}
}
8. Constructor Overloading
 A class can have multiple constructors with different signatures (different number or
types of parameters). This allows for flexibility in object creation.
 Example:
C#
public class Employee
{
public Employee() { } // Default constructor
public Employee(int id) { Id = id; }
public Employee(int id, string name)
{
Id = id;
Name = name;
}
}
9. Important Points
 Constructors cannot have a return type, not even void.
 Constructors cannot be inherited.
 A class can only have one constructor with no parameters (default constructor).
10. Diagram: Class with Constructors

Opens in a new window


stackoverflow.com
class diagram showing a class with a default constructor and a parameterized
constructor
11. Code Example (Combining Different Concepts)
C#
using System;

public class Program


{
public static void Main(string[] args)
{
// Create objects using different constructors
Employee employee1 = new Employee(); // Default constructor
Employee employee2 = new Employee(1); // Parameterized constructor with one
argument
Employee employee3 = new Employee(2, "John Doe"); // Parameterized
constructor with two arguments

// Access and display employee information


Console.WriteLine(employee1.Id); // Output: 0
Console.WriteLine(employee2.Id); // Output: 1
Console.WriteLine(employee3.Id); // Output: 2
Console.WriteLine(employee3.Name); // Output: John Doe

Console.ReadLine();
}
}

public class Employee


{
public int Id { get; set; }
public string Name { get; set; }
public Employee() // Default constructor
{
Console.WriteLine("Default Constructor Called");
}

public Employee(int id) // Parameterized constructor with one argument


{
Id = id;
Console.WriteLine("Parameterized Constructor (1 argument) Called");
}

public Employee(int id,


Static vs. Non-Static Constructors in C#
1. Introduction
 Constructors: Special methods within a class that are automatically called when an
object of that class is created. Their primary role is to initialize the object's state
(properties/fields).
 Static Constructor: A special type of constructor that is declared with the static
keyword.
 Non-Static Constructor (Instance Constructor): A constructor that is not declared
with the static keyword.
2. Key Differences
Non-Static Constructor
Feature Static Constructor
(Instance Constructor)
Called automatically once Called explicitly when an
Execution when the class is first object of the class is
loaded or accessed. created.
Initialize static members Initialize instance members
Purpose (fields, properties) of the (fields, properties) of each
class. object.
Cannot have access
Access
modifiers (public, private, Can have access modifiers.
Modifiers
protected).
Can have parameters
Parameters Cannot have parameters. (parameterized
constructor).
Overloading Cannot be overloaded. Can be overloaded.
Call Executed only once per Executed once for each
Frequency application execution. object created.

Export to Sheets
3. Examples
 Static Constructor:
C#
public class MyClass
{
public static int StaticCount;

static MyClass()
{
Console.WriteLine("Static Constructor Called");
StaticCount = 0;
}

// ... other members ...


}
 Non-Static Constructor:
C#
public class MyClass
{
public int InstanceCount;

public MyClass()
{
Console.WriteLine("Non-Static Constructor Called");
InstanceCount = 1;
}

// ... other members ...


}
4. When is the Static Constructor Executed?
 First Access to the Class: The static constructor is executed the first time any
member of the class is accessed (static or instance member).
 Creating an Instance: If an instance of the class is created, the static constructor is
executed before the instance constructor.
5. Important Points
 Static constructors cannot be called explicitly.
 Static constructors can only access static members of the class.
 If a class contains static fields, the compiler automatically generates a static
constructor to initialize them.
 Non-static constructors are called when an object of the class is created using the new
operator.
6. Code Example
C#
using System;

public class Program


{
public static void Main(string[] args)
{
Console.WriteLine("Main Method Started");
// Accessing a static member will trigger the static constructor
Console.WriteLine(MyClass.StaticCount);

// Creating an object will trigger the static constructor (if not already triggered)
// and then the instance constructor
MyClass obj1 = new MyClass();

MyClass obj2 = new MyClass();

Console.WriteLine("Main Method Ended");


Console.ReadLine();
}
}

public class MyClass


{
public static int StaticCount;

static MyClass()
{
Console.WriteLine("Static Constructor Called");
StaticCount = 0;
}

public int InstanceCount;

public MyClass()
{
Console.WriteLine("Non-Static Constructor Called");
InstanceCount = 1;
}
}
7. Diagram

Openindownaveen-metta.medium.com
class diagram illustrating the execution order of static and nonstatic constructors
8. Conclusion
 Static and non-static constructors play crucial roles in object initialization in C#.
 Understanding their differences and how they are executed is essential for writing
efficient and well-structured C# code.
 By effectively using static and non-static constructors, you can manage the
initialization of class members and control the execution flow within your classes.

Private Constructors in C#
1. Introduction
 A private constructor is a constructor declared with the private access modifier.
 It restricts object creation from outside the class.
2. Key Characteristics
 Access: Can only be accessed within the class itself.
 Object Creation:
o Cannot be used to create objects directly from outside the class.
o Can be used to create objects within the same class.
 Inheritance:
o If a class has only a private constructor, it cannot be inherited by other classes
(except nested classes within the same class).
3. Examples
 Private Constructor Only:
C#
public class MyClass
{
private MyClass()
{
Console.WriteLine("Private Constructor Called");
}

public void SomeMethod()


{
// ...
}
}

// In another class (outside MyClass)


MyClass obj = new MyClass(); // Compile-time error: 'MyClass.MyClass()' is
inaccessible
 Private and Public Constructors:
C#
public class MyClass
{
private MyClass()
{
Console.WriteLine("Private Constructor Called");
}
public MyClass(string message)
{
Console.WriteLine("Public Constructor Called");
}

public void SomeMethod()


{
// ...
}
}

// In another class (outside MyClass)


MyClass obj = new MyClass("Hello"); // Creates an object using the public
constructor
 Creating Objects within the Class:
C#
public class MyClass
{
private MyClass()
{
Console.WriteLine("Private Constructor Called");
}

public static MyClass CreateInstance()


{
return new MyClass();
}

public void SomeMethod()


{
// ...
}
}

// In another class (outside MyClass)


MyClass obj = MyClass.CreateInstance(); // Creates an object using a static factory
method
4. Use Cases
 Singleton Pattern: Ensures only one instance of a class exists throughout the
application.
 Utility Classes: For classes that provide static methods and do not require object
instantiation.
 Nested Classes: For inner classes that are closely related to the outer class and should
not be instantiated independently.
5. Important Notes
 A class with only a private constructor can still be inherited by nested classes within
the same class.
 A private constructor does not restrict inheritance if the class also has a public
constructor.
 If a class has only a private constructor and no other constructors, it cannot be
inherited by classes outside its scope.
6. Singleton Pattern Implementation
C#
public sealed class Singleton
{
private static Singleton instance;
private static readonly object lockObject = new object();

private Singleton()
{
// ...
}

public static Singleton GetInstance()


{
lock (lockObject)
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
7. Conclusion
 Private constructors are a valuable tool in C# for controlling object creation and
enforcing design patterns.
 They can be used to restrict object creation from outside the class, ensuring that
objects are created in a controlled and predictable manner.
 Understanding the limitations and use cases of private constructors is crucial for
effective object-oriented design.

Destructors in C#
1. Introduction
 A destructor is a special method in C# that is automatically called by the garbage
collector when an object is no longer in use.
 Its primary purpose is to perform any necessary cleanup operations before the object's
memory is reclaimed.
2. Key Characteristics
 Name: The destructor's name is the same as the class name preceded by a tilde (~).
 Access Modifier: Destructors cannot have any access modifiers (public, private,
protected).
 Parameters: Destructors cannot have any parameters.
 Return Type: Destructors do not have a return type.
 Execution:
o Called implicitly by the garbage collector when the object is eligible for
garbage collection.
o The exact timing of destructor execution is not deterministic.
3. When is an Object Eligible for Garbage Collection?
 When all references to the object have been lost.
 When the application terminates.
4. Example
C#
public class MyClass
{
public MyClass()
{
Console.WriteLine("Constructor Called");
}

~MyClass()
{
Console.WriteLine("Destructor Called");
}
}
5. Calling the Garbage Collector
 You can request the garbage collector to run by calling GC.Collect().
 However, relying heavily on GC.Collect() can negatively impact performance.
6. Destructor Implementation
 Destructors are implemented using the Finalize method in the .NET runtime.
 The Finalize method is called recursively for all objects in the inheritance chain.
7. Important Points
 Destructors cannot be called explicitly.
 Destructors should be used sparingly and only when necessary to release unmanaged
resources (e.g., file handles, database connections).
 Relying heavily on destructors can negatively impact performance.
8. Dispose Pattern
 The preferred way to release unmanaged resources is by implementing the
IDisposable interface and providing a Dispose() method.
 The Dispose() method allows for explicit resource cleanup and provides more control
over the timing of resource release.
 The Dispose() method should be called by the user of the object when they are
finished with it.
9. Code Example (Dispose Pattern)
C#
public class MyClass : IDisposable
{
private bool disposedValue = false; // To detect redundant calls

protected virtual void Dispose(bool disposing)


{
if (!disposedValue)
{
if (disposing)
{
// Dispose managed resources here
}

// Dispose unmanaged resources here


disposedValue = true;
}
}

~MyClass()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}

public void Dispose()


{
Dispose(true);
GC.SuppressFinalize(this);
}
}
10. Conclusion
 Destructors are a crucial mechanism for cleaning up unmanaged resources in C#.
 While destructors are automatically called by the garbage collector, it's important to
use them judiciously and consider using the IDisposable interface for more control
over resource management.
 By following best practices for resource management, you can improve the
performance and stability of your applications.

Garbage Collection in .NET Framework


Understanding Memory Management
In a .NET application, you create objects using the new keyword. These objects reside
in memory, and as your application grows, the memory usage can increase. Manually
managing memory allocation and deallocation can be complex and error-prone. This
is where Garbage Collection (GC) comes in.
What is Garbage Collection?
Garbage Collection (GC) is an automatic memory management system in the .NET
Framework. It helps to:
 Allocate memory for objects
 Release memory that is no longer being used by the application
Benefits of Garbage Collection:
 Reduces development complexity by eliminating manual memory management.
 Minimizes the risk of memory leaks, which can lead to performance issues and
crashes.
Generations in Garbage Collection
The .NET GC uses a generational model to optimize memory management. Objects
are categorized into three generations:
 Generation 0 (Gen 0): This generation holds newly created objects. It's frequently
collected due to the high probability of short-lived objects.
 Generation 1 (Gen 1): Objects that survive a Gen 0 collection are promoted to Gen
1. These objects tend to have a longer lifespan but are not permanent. Gen 1 is
collected less frequently than Gen 0.
 Generation 2 (Gen 2): Objects that survive multiple collections in Gen 0 and Gen 1
are promoted to Gen 2. These are long-lived objects that remain in memory for a
longer duration. Gen 2 is collected the least frequently.
Diagram:
+-------------------+
| New | --> Gen 0 (Frequently Collected)
+-------------------+
|
v
+-------------------+
| Survive Gen 0 | --> Gen 1 (Less Frequently Collected)
+-------------------+
|
v
+-------------------+
| Long-Lived Objects| --> Gen 2 (Least Frequently Collected)
+-------------------+
Impact of Destructors on Garbage Collection
Destructors are methods with a tilde (~) preceding the class name. They are intended
to perform cleanup tasks for unmanaged resources (e.g., file handles, database
connections) before an object is garbage collected. However, using destructors for
cleanup can create a double garbage collection loop:
1. The GC identifies an object with a destructor and keeps it in memory instead of
immediate collection.
2. The destructor is called later, and then the object is finally collected.
This loop can negatively impact performance, especially for short-lived objects.
Solution: Finalize Dispose Pattern
To avoid the double garbage collection loop and properly release unmanaged
resources, use the IDisposable interface and the Dispose pattern:
1. Implement the IDisposable interface in your class.
2. Provide a Dispose method for releasing unmanaged resources.
3. Call GC.SuppressFinalize(this) within the Dispose method to prevent the destructor
from being called.
4. In your application code, call the Dispose method when you are finished using the
object.
Example:
C#
public class MyClass : IDisposable
{
private bool disposedValue = false;

protected virtual void Dispose(bool disposing)


{
if (!disposedValue)
{
if (disposing)
{
// Release managed resources
}

// Release unmanaged resources


disposedValue = true;
}
}

public void Dispose()


{
Dispose(true);
GC.SuppressFinalize(this);
}

~MyClass()
{
Dispose(false);
}
}
By following these practices, you can ensure efficient memory management and
prevent memory leaks in your .NET applications.
Additional Notes
 The GC is a complex system with various configurations and settings you can explore
for advanced memory management scenarios.
 Tools like the .NET Memory Profiler can help you analyze memory usage and
identify potential issues.

Differences Between Finalize and Dispose in C#


1. Purpose
 Finalize: Primarily used to release unmanaged resources (e.g., file handles, database
connections) when an object is garbage collected.
 Dispose: Used to release both managed and unmanaged resources in a deterministic
and controlled manner.
2. Invocation
 Finalize: Called implicitly by the garbage collector when the object is no longer
reachable. The timing of the call is non-deterministic.
 Dispose: Called explicitly by the programmer using the Dispose() method. This
provides more control over when resources are released.
3. Control
 Finalize: Offers limited control over the timing of resource release.
 Dispose: Provides more control over the timing of resource release, allowing for
immediate resource cleanup.
4. Determinism
 Finalize: Non-deterministic. The exact time of execution is not guaranteed.
 Dispose: Deterministic. The programmer controls when the Dispose() method is
called, enabling precise resource release.
5. Inheritance
 Finalize: Inherited from the Object class. If overridden, it should always call the base
class Finalize method to ensure proper cleanup.
 Dispose: Part of the IDisposable interface.
6. Resource Management
 Finalize: Primarily for unmanaged resources.
 Dispose: For both managed and unmanaged resources.
7. Performance
 Finalize: Can impact performance due to the unpredictable nature of garbage
collection.
 Dispose: Generally more efficient as it provides more control over resource release.
8. Example
C#
public class ResourceHolder : IDisposable
{
private bool disposedValue = false; // To detect redundant calls

protected virtual void Dispose(bool disposing)


{
if (!disposedValue)
{
if (disposing)
{
// Dispose managed resources here (e.g., other objects)
}

// Dispose unmanaged resources here


// ...
disposedValue = true;
}
}

~ResourceHolder()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}

public void Dispose()


{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Key Considerations
 IDisposable: Always prefer using the IDisposable interface and the Dispose method
for resource management.
 Finalizer: Use Finalizers sparingly, primarily for unmanaged resources when there is
no guarantee that Dispose will be called.
 Dispose Pattern: Follow the dispose pattern to ensure proper resource cleanup and
avoid double garbage collection.
 GC.SuppressFinalize: Call GC.SuppressFinalize(this) in the Dispose method to
prevent the garbage collector from calling the finalizer if Dispose has already been
called.
Summary
 Finalize and Dispose are both mechanisms for resource cleanup in C#.
 Dispose provides more control, determinism, and performance benefits.
 Use Dispose whenever possible and rely on Finalize only when necessary for
unmanaged resources and when there's no guarantee that Dispose will be called.

Absolutely, here's a comprehensive response to the prompt combining the strengths of


both Response A and Response B, addressing their shortcomings, and incorporating
insights from the ratings:
Access Specifiers in C#
In object-oriented programming (OOP), access specifiers are keywords that control
the visibility and accessibility of classes, members (variables, properties, methods,
constructors, etc.), and other constructs within your code. They play a crucial role in
promoting data encapsulation and code organization, ensuring that only authorized
parts of your program can interact with specific elements.
Types of Access Specifiers in C#
C# supports six primary access specifiers:
1. Private: Members declared as private are only accessible within the class they are
defined in. This level of encapsulation restricts access to other classes, even those
derived from the containing class, within the same assembly.
2. Public: Public members are accessible from anywhere within the program, regardless
of the namespace or assembly in which they are declared. This is typically used for
exposing functionality or data that needs to be consumed by other parts of your
application.
3. Protected: Protected members are accessible from within the containing class and its
derived classes, but not from other unrelated classes, even within the same assembly.
This enforces a hierarchical access model where derived classes can inherit and
potentially extend the functionality of protected members.
4. Internal: Internal members are accessible from within the same assembly where they
are declared. This is useful for restricting access to classes and members that should
only be used by other classes within the same project or application.
5. Protected Internal: This access specifier combines aspects of protected and internal.
Members declared as protected internal are accessible from within the containing
class, its derived classes (regardless of assembly), and other classes within the same
assembly.
6. Private Protected (C# 7.2+): Introduced in C# 7.2, private protected members are
accessible only from the containing class and its derived classes within the same
assembly. This provides a more granular level of control compared to protected
access, restricting visibility to derived classes within the same application.
Understanding Type and Type Members
 Types: In C#, types refer to classes, structs, enums, interfaces, and delegates. They
represent blueprints for creating objects with specific characteristics and behaviors.
 Type Members: These are the elements that make up a type, including variables,
properties, methods, constructors, and events. They define the internal state and
functionality of the type. By default, if no access specifier is explicitly provided, type
members are considered private.
Access Specifiers with Type Members
The following table summarizes the access specifier options for type members and
their corresponding visibility:
Access Specifier Visibility
Private Within the containing class
Public Anywhere in the program
Protected Within the class and derived classes (same assembly)
Internal Within the same assembly
Protected Within the class, derived classes (any assembly), and same
Internal assembly
Private Protected Within the class and derived classes (same assembly)
Export to Sheets
Access Specifiers with Types
While all six access specifiers can be used with type members, only two are valid for
types themselves:
 Public: Public types can be accessed from anywhere in the program, allowing other
parts of your code to create instances and interact with them.
 Internal: Internal types are restricted to the same assembly, preventing direct usage
from other assemblies. By default, if no access specifier is specified for a type, it's
considered internal.
Example: Understanding Access Specifiers
Let's create a simple example to illustrate the concepts:
C#
public class AssemblyOneClass1
{
private int id; // Private member, only accessible within AssemblyOneClass1

public void Display1()


{
Console.WriteLine(id); // Accessing private member within the class
}
}

public class AssemblyOneClass2 : AssemblyOneClass1 // Derived class


{
// Cannot access private member directly from AssemblyOneClass2
// due to its private access
}

public class AnotherAssemblyClass // Class from a different assembly


{
// Cannot access AssemblyOneClass1 directly because it's internal
// (assuming it's not declared as public)
}
In this example:
 id is a private member, accessible only within AssemblyOneClass1.
 Display1() can access id because it's within the same class.
 AssemblyOneClass2 cannot directly access id due to its private scope.

Absolutely, here's a comprehensive response combining the strengths of the previous


ones, addressing their shortcomings, and incorporating insights from the ratings to
create exceptional exam notes on Encapsulation in C#:
Encapsulation in C#
Encapsulation is a fundamental principle of object-oriented programming (OOP) that
promotes data protection and code organization. It involves bundling data (often
called state or member variables) and the methods (functions that operate on the data)
that manipulate it into a single unit called a class. This unit controls access to its
internal components, ensuring data integrity and promoting better code
maintainability.
Key Concepts
1. Access Specifiers: These keywords define the visibility and accessibility of members
within a class. C# offers six access specifiers:
o Public: Accessible from anywhere in the program.
o Private: Accessible only within the class.
o Protected: Accessible within the class and derived classes (same assembly).
o Internal: Accessible within the same assembly.
o Protected Internal: Accessible within the class, derived classes (any
assembly), and same assembly.
o Private Protected (C# 7.2+): Accessible only within the class and derived
classes (same assembly).
2. Data Hiding: By declaring variables as private, you restrict direct access from
outside the class. Access to these variables is then controlled through public methods
(setters and getters) or properties. This promotes data security and allows for
validation logic to be applied before modifying the data.
Benefits of Encapsulation
 Data Protection: Encapsulation allows you to control how data is accessed and
modified, preventing accidental or malicious changes.
 Data Hiding: Sensitive data is hidden from external code, enhancing security.
 Improved Code Maintainability: Changes to how data is stored or accessed can be
made within the class without affecting other parts of the program that rely on its
public interface.
 Validation: You can implement validation logic in setter methods or properties to
ensure only valid data is assigned to variables.
 Increased Modularity: Code becomes more modular and organized by grouping
related data and behavior within a single unit.
Implementation Examples
1. Using Setter and Getter Methods
C#
public class BankAccount
{
private double _balance;

public double GetBalance()


{
return _balance;
}

public void SetBalance(double value)


{
if (value < 0)
{
throw new ArgumentException("Balance cannot be negative.");
}
_balance = value;
}
}
In this example, _balance is a private variable. The GetBalance() method allows
reading the balance, and the SetBalance() method allows setting the balance with
validation to ensure non-negative values.
2. Using Properties
C#
public class BankAccount
{
private double _balance;

public double Balance


{
get { return _balance; }
set
{
if (value < 0)
{
throw new ArgumentException("Balance cannot be negative.");
}
_balance = value;
}
}
}
This example achieves the same functionality as the previous one using a property
named Balance. Properties provide a cleaner syntax for accessing and modifying
private variables.

Abstraction in C#
Abstraction is a fundamental concept in object-oriented programming (OOP) that focuses on
exposing essential functionalities (what an object does) while hiding implementation details (how it
does it). It simplifies complex systems by breaking them down into smaller, more manageable units.
This promotes code reusability, maintainability, and flexibility.
Key Concepts
 Focus on Behavior: Define the services (methods) an object provides without revealing the
underlying logic. Users interact with these services without needing to know the intricate
workings of the object.
 Data Hiding: Encapsulate data (member variables) within a class and control access through
methods (getters and setters) or properties. This safeguards data integrity and prevents
unauthorized modifications.
 Interfaces: Define contracts outlining the services an object must implement. Classes can
inherit from interfaces and provide concrete implementations for the specified methods.
This promotes loose coupling and allows for interchangeable implementations.
 Abstract Classes: Serve as blueprints for derived classes by defining a set of abstract
methods (without implementation) and potentially concrete methods. Derived classes
inherit and provide implementations for abstract methods, achieving partial or complete
abstraction.
Benefits of Abstraction
 Simplified Code: Users focus on how to utilize an object's services without getting bogged
down in implementation details.
 Increased Maintainability: Changes to internal workings don't necessarily affect how users
interact with the object, making modifications easier and less error-prone.
 Enhanced Reusability: Well-abstracted components can be reused in different contexts
without modification, promoting code efficiency.
 Improved Security: Sensitive data can be protected by restricting access through methods
and properties, preventing unauthorized modifications.
 Flexibility in Design: Abstract classes and interfaces facilitate the creation of interchangeable
implementations, fostering a more flexible and adaptable codebase.
Implementation Examples
1. Abstraction Using Interfaces
C#
public interface IShape
{
double CalculateArea();
}

public class Circle : IShape


{
public double Radius { get; set; }

public double CalculateArea()


{
return Math.PI * Radius * Radius;
}
}

public class Square : IShape


{
public double SideLength { get; set; }

public double CalculateArea()


{
return SideLength * SideLength;
}
}

public class AreaCalculator


{
public double CalculateShapeArea(IShape shape)
{
return shape.CalculateArea();
}
}

// Usage
IShape circle = new Circle { Radius = 5 };
IShape square = new Square { SideLength = 3 };

AreaCalculator calc = new AreaCalculator();


double circleArea = calc.CalculateShapeArea(circle);
double squareArea = calc.CalculateShapeArea(square);

Console.WriteLine($"Circle Area: {circleArea}");


Console.WriteLine($"Square Area: {squareArea}");
In this example, the IShape interface defines a contract for calculating the area of a shape. Circle and
Square implement this interface with their specific area calculation logic, but the AreaCalculator class
only depends on the IShape interface, making it usable with any object that implements IShape.
2. Abstraction Using Abstract Classes
C#
public abstract class Shape
{
public abstract double CalculateArea();
}

public class Circle : Shape


{
public double Radius { get; set; }

public override double CalculateArea()


{
return Math.PI * Radius * Radius;
}
}

public class Square : Shape


{
public double SideLength { get; set; }

public override double CalculateArea()


{
return SideLength * SideLength;
}
}

public class AreaCalculator


{
public double CalculateShapeArea(Shape shape)
{
return shape.CalculateArea();
}
}

// Usage
Shape circle = new Circle { Radius = 5 };
Shape square = new Square { SideLength = 3 };

AreaCalculator calc = new AreaCalculator();


double circleArea = calc.CalculateShapeArea(circle);
double squareArea = calc.CalculateShapeArea(square);

Console.WriteLine($"Circle Area: {circleArea}");


Console.WriteLine($"Square Area: {squareArea}");
This example is similar to the previous one, but it uses an abstract class Shape that defines the
CalculateArea method as abstract. Derived classes like Circle and Square provide concrete
implementations for this method, achieving abstraction for the area calculation logic.
Inheritance in C#
1. Definition
 Inheritance is a fundamental concept in object-oriented programming that allows a class
(called the derived class, subclass, or child class) to inherit properties and behaviors
(methods) from another class (called the base class, superclass, or parent class).
 This promotes code reusability and helps to organize code into a hierarchical structure.
2. Key Concepts
 Parent/Base/Superclass: The class from which other classes inherit.
 Child/Derived/Subclass: The class that inherits properties and behaviors from the parent
class.
 Inheritance Relationship: Established using the colon (:) syntax: class DerivedClass :
BaseClass { ... }
3. Rules of Inheritance
 Rule 1: Parent Class Constructor Accessibility:
o The child class constructor implicitly calls the parent class constructor.
o The parent class constructor must be accessible (public or protected) to the child
class.
o If the parent class constructor is parameterized, the child class constructor must
explicitly call the parent class constructor using the base() keyword and provide the
required arguments.
 Rule 2: Access to Parent Class Members:
o Child classes can access all public and protected members of the parent class.
o Child classes cannot directly access private members of the parent class.
o Parent classes cannot access members that are exclusively defined in the child class.
 Rule 3: Reference Variables and Inheritance:
o A parent class reference variable can be used to refer to an instance of the child
class.
o However, using a parent class reference, you can only access members of the parent
class. You cannot access members that are exclusively defined in the child class.
 Rule 4: Object Class as the Ultimate Parent:
o Every class in C# implicitly inherits from the Object class, which provides
fundamental methods like Equals(), GetHashCode(), GetType(), and ToString().
 Rule 5: Single Inheritance (with Classes)
o C# supports single inheritance with classes. This means a class can only inherit from
one immediate parent class.
 Rule 6: Calling Parent Class Constructors:
o If the parent class constructor is parameterized, the child class constructor must
explicitly call the parent class constructor using the base() keyword and provide the
necessary arguments.
Example
C#
class Animal
{
public void MakeSound()
{
Console.WriteLine("Generic animal sound");
}
}

class Dog : Animal


{
public void Bark()
{
Console.WriteLine("Woof!");
}
}

class Program
{
static void Main(string[] args)
{
Dog myDog = new Dog();
myDog.MakeSound(); // Inherited from Animal
myDog.Bark(); // Defined in Dog
}
}
Benefits of Inheritance
 Code Reusability: Avoids code duplication by inheriting common properties and behaviors
from a parent class.
 Improved Code Organization: Creates a hierarchical structure that reflects real-world
relationships.
 Enhanced Maintainability: Changes made to the parent class are automatically reflected in
all derived classes.
 Extensibility: Allows for the creation of specialized classes by adding new features or
modifying existing behavior.
Key Points
 Inheritance is a powerful tool for creating flexible and reusable code.
 Understanding the rules of inheritance is crucial for effective object-oriented design.
 Utilize inheritance judiciously to maintain a well-structured and maintainable codebase.
Types of Inheritance in C#
In C#, inheritance can be broadly classified into two main types:
1. Implementation Inheritance
 Definition: This type of inheritance occurs when a class derives from another class.
 Characteristics:
o The derived class inherits both data members (fields) and member functions
(methods) from the base class.
o It allows for code reuse and promotes a hierarchical relationship between classes.
o Subtypes:
 Single Inheritance: A class inherits from only one immediate base class.
(e.g., class DerivedClass : BaseClass { ... })
 Multi-level Inheritance: A chain of inheritance where a class inherits from
another derived class. (e.g., class A { ... }, class B : A { ... }, class C : B { ... })
 Hierarchical Inheritance: Multiple classes inherit from a single base class.
(e.g., class A { ... }, class B : A { ... }, class C : A { ... })
2. Interface Inheritance
 Definition: This type of inheritance occurs when a class implements an interface.
 Characteristics:
o A class that implements an interface must provide concrete implementations for all
the methods declared in the interface.
o Interfaces define a contract that classes must adhere to.
o Allows for polymorphism and loose coupling between classes.
Key Points:
 Multiple Inheritance (with Classes): C# does not directly support multiple inheritance with
classes. This means a class cannot inherit from multiple base classes directly.
 Hybrid Inheritance: A combination of various inheritance types (single, multi-level,
hierarchical) can be considered hybrid inheritance. However, it's not a distinct category in C#.
Example: Implementation Inheritance
C#
public class Animal
{
public void MakeSound()
{
Console.WriteLine("Generic animal sound");
}
}

public class Dog : Animal


{
public void Bark()
{
Console.WriteLine("Woof!");
}
}
In this example, the Dog class inherits from the Animal class, demonstrating single inheritance.
Example: Interface Inheritance
C#
public interface IShape
{
double CalculateArea();
}

public class Circle : IShape


{
public double Radius { get; set; }

public double CalculateArea()


{
return Math.PI * Radius * Radius;
}
}
In this example, the Circle class implements the IShape interface, providing its own implementation
for the CalculateArea() method.
In Summary
 Implementation inheritance focuses on inheriting data members and member functions
from a base class.
 Interface inheritance focuses on adhering to a contract defined by an interface.
 Understanding these types of inheritance is crucial for effective object-oriented design and
development in C#.
Understanding IS-A and HAS-A Relationships in C#
In object-oriented programming (OOP), particularly in C#, two fundamental relationships exist
between classes: IS-A (inheritance) and HAS-A (composition). These relationships define how classes
interact and structure your code effectively.
IS-A (Inheritance)
 Definition: The IS-A relationship represents a hierarchical connection between a base class
(parent) and derived class (child). The derived class inherits properties and behaviors from
the base class, essentially becoming a specialized version of it.
 Characteristics:
o Inheritance: The derived class inherits data members (fields) and member functions
(methods) from the base class.
o Polymorphism: The derived class can override or extend functionalities inherited
from the base class.
o Substitutability: Objects of the derived class can be used wherever objects of the
base class are expected (within certain limitations).
 Example:
C#
class Animal
{
public void MakeSound()
{
Console.WriteLine("Generic animal sound");
}
}

class Dog : Animal


{
public void Bark()
{
Console.WriteLine("Woof!");
}
}
Here, Dog inherits from Animal, making Dog an IS-A type of Animal.
HAS-A (Composition)
 Definition: The HAS-A relationship describes a compositional relationship. It signifies that
one class ("container") contains or is composed of objects from another class. This
relationship is looser than inheritance.
 Characteristics:
o Composition: The container class has an instance (object) of another class as a
member variable.
o Independence: The contained object can exist independently of the container class.
o Encapsulation: The internal workings of the contained object are usually hidden
from the outside container class.
o Flexibility: Objects can be easily replaced or modified without affecting the
container class.
 Example:
C#
class Address
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
}

class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
}
Here, Employee HAS-A Address through the member variable Address.
Key Differences
Feature IS-A (Inheritance) HAS-A (Composition)
Nature Inheritance (parent-child) Compositional
Coupling Stronger Looser
Usage Extension, specialization Requires functionality/properties
Flexibility Limited (tightly bound) More flexible (easily modified)
Export to Sheets
Choosing the Right Relationship
The choice between IS-A and HAS-A depends on the nature of the relationship between your classes.
Ask yourself:
 Is the derived class a specialized version of the base class? (IS-A)
 Does the container class need functionalities provided by another class's object? (HAS-A)
Here's a quick guideline:
 If the statement "DerivedClass IS-A BaseClass" makes sense, use inheritance.
 If the statement "ContainerClass HAS-A AnotherClass" makes sense, use composition.
Remember
 Inheritance is implemented using the : syntax (e.g., class DerivedClass : BaseClass { ... }).
 Composition is simply declaring a variable of another class inside a class.
Generalization and Specialization in C#
Generalization
 Concept:
o Identifying commonalities among a group of existing classes and creating a new,
more general (parent) class.
o This parent class encapsulates the shared features of the child classes.
 Example:
o Consider classes like Circle, Square, and Rectangle. They all share the concept of
being "shapes."
o We can create a generalized class called Shape that includes common properties like
Area and Perimeter.
o Circle, Square, and Rectangle would then inherit from the Shape class, inheriting the
common properties and implementing their specific area and perimeter calculations.
Specialization
 Concept:
o Creating new, more specialized classes (child classes) from an existing base class.
o These derived classes inherit the properties and behaviors of the base class and add
their own unique characteristics.
 Example:
o You have a base class Animal with general characteristics like Eat() and Sleep().
o You can create specialized classes like Dog, Cat, and Bird that inherit from Animal
and add specific behaviors like Bark(), Meow(), and Fly().
Key Differences
Feature Generalization Specialization
Direction Bottom-up (from specific to general) Top-down (from general to specific)
Purpose Identify commonalities, create a superclass Create specialized versions of a base class
Base Class Created after child classes exist Already exists
Export to Sheets
In C#
 Generalization: Often achieved using interfaces or abstract classes.
 Specialization: Achieved through class inheritance.
Example (Generalization)
C#
interface IShape
{
double CalculateArea();
}

class Circle : IShape


{
// ...
}

class Rectangle : IShape


{
// ...
}

class Square : IShape


{
// ...
}
Example (Specialization)
C#
class Animal
{
public void MakeSound()
{
Console.WriteLine("Generic animal sound");
}
}

class Dog : Animal


{
public void Bark()
{
Console.WriteLine("Woof!");
}
}
In summary:
 Generalization is about identifying commonalities and creating a more abstract class.
 Specialization is about creating more specific classes from a general base class.
 Both are crucial for designing well-structured and maintainable object-oriented systems.
Abstract Classes and Abstract Methods in C#
Abstract Methods
 Definition: An abstract method is a method declared within an abstract class or an interface
that has no implementation. It only contains a signature (method name, return type, and
parameters).
 Declaration:
C#
public abstract void MyMethod();
 Purpose:
o To define a contract that derived classes must fulfill.
o To provide a common interface for derived classes.
Abstract Classes
 Definition: A class declared with the abstract keyword. It can contain both abstract and non-
abstract methods.
 Characteristics:
o Cannot be instantiated directly.
o Serves as a blueprint for other classes.
o Must be inherited by other classes.
o Derived classes must provide implementations for all inherited abstract methods.
Key Points
 Relationship: Abstract methods are typically declared within abstract classes.
 Implementation: Abstract methods must be implemented by derived classes.
 Instantiation: Abstract classes cannot be instantiated.
 Purpose:
o Enforce a common structure and behavior among derived classes.
o Promote code reusability.
o Support polymorphism.
Example
C#
public abstract class Shape
{
public abstract double CalculateArea();

public virtual void Display()


{
Console.WriteLine("This is a shape.");
}
}

public class Circle : Shape


{
public double Radius { get; set; }

public override double CalculateArea()


{
return Math.PI * Radius * Radius;
}
}

public class Rectangle : Shape


{
public double Width { get; set; }
public double Height { get; set; }

public override double CalculateArea()


{
return Width * Height;
}
}
In this example:
 Shape is an abstract class with an abstract method CalculateArea().
 Circle and Rectangle are derived classes that implement the CalculateArea() method
according to their specific shapes.
When to Use Abstract Classes and Methods
 Define a Common Interface: When you need to define a common set of methods that must
be implemented by derived classes.
 Enforce a Contract: To ensure that derived classes adhere to a specific contract or set of
rules.
 Promote Code Reusability: To share common functionality among derived classes.
 Implement Polymorphism: To enable polymorphic behavior where objects of different
derived classes can be treated as objects of the base class.
 Create Frameworks: To create flexible frameworks where derived classes can extend and
customize the base functionality.
Interfaces in C#
What is an Interface?
 An interface in C# is a blueprint that defines a contract or a set of rules that a class must
adhere to.
 It specifies a list of methods, properties, events, or indexers that a class implementing the
interface must provide.
 Interfaces themselves cannot be instantiated.
Key Characteristics
 All members of an interface are implicitly public and abstract.
 Interfaces can only contain method signatures (no method bodies), properties, events, and
indexers.
 Interfaces cannot contain fields, constructors, or destructors.
 A class can implement multiple interfaces.
 A class that implements an interface must provide concrete implementations for all
members of the interface.
How to Define an Interface
C#
interface IMyInterface
{
void MyMethod();
int MyProperty { get; set; }
event EventHandler MyEvent;
}
Example
C#
interface IShape
{
double CalculateArea();
}

class Circle : IShape


{
public double Radius { get; set; }

public double CalculateArea()


{
return Math.PI * Radius * Radius;
}
}

class Rectangle : IShape


{
public double Width { get; set; }
public double Height { get; set; }

public double CalculateArea()


{
return Width * Height;
}
}
In this example:
 IShape is an interface that defines a contract for calculating the area of a shape.
 Circle and Rectangle classes implement the IShape interface and provide their own
implementations for the CalculateArea() method.
When to Use Interfaces
 Define a Common Contract: To enforce a common set of methods that must be
implemented by different classes.
 Achieve Polymorphism: To treat objects of different classes uniformly.
 Support Multiple Inheritance: Since C# does not support multiple inheritance for classes,
interfaces provide a way to achieve similar behavior.
 Loose Coupling: Interfaces promote loose coupling between classes.
 Testing and Mocking: Interfaces are crucial for unit testing, allowing you to create mock
implementations for dependencies.
 Dependency Injection: Interfaces are often used in dependency injection frameworks to
inject dependencies into classes.
Benefits of Using Interfaces
 Flexibility: Interfaces provide flexibility in design and implementation.
 Reusability: Interfaces promote code reusability by defining common contracts.
 Maintainability: Interfaces make code more maintainable by improving modularity and
reducing dependencies.
 Testability: Interfaces facilitate unit testing by enabling the creation of mock objects.
 Extensibility: Interfaces make it easier to extend functionality by creating new classes that
implement the interface.
In Summary
Interfaces are a fundamental concept in object-oriented programming in C#. They provide a powerful
mechanism for defining contracts, promoting code reusability, and achieving polymorphism. By
understanding and effectively using interfaces, you can create more flexible, maintainable, and
testable applications.
nterface Real-Time Example in C#
This example demonstrates how to use interfaces to model bank accounts in a C# application.
1. Define the Interface:
C#
interface IBankAccount
{
bool DepositAmount(decimal amount);
bool WithdrawAmount(decimal amount);
decimal CheckBalance();
}
This interface defines the core functionalities that any type of bank account should provide:
 DepositAmount(decimal amount): Deposits a specified amount into the account. Returns
true if successful, false otherwise.
 WithdrawAmount(decimal amount): Withdraws a specified amount from the account.
Returns true if successful, false otherwise.
 CheckBalance(): Returns the current balance of the account.
2. Create Concrete Account Classes:
 SavingAccount.cs
C#
public class SavingAccount : IBankAccount
{
private decimal _balance = 0;
private readonly decimal _perDayWithdrawLimit = 10000;
private decimal _todayWithdrawal = 0;

public bool DepositAmount(decimal amount)


{
_balance += amount;
Console.WriteLine($"You have Deposited: {amount}");
Console.WriteLine($"Your Account Balance: {_balance}");
return true;
}

public bool WithdrawAmount(decimal amount)


{
if (_balance < amount)
{
Console.WriteLine("You have Insufficient balance!");
return false;
}
else if (_todayWithdrawal + amount > _perDayWithdrawLimit)
{
Console.WriteLine("Withdrawal attempt failed!");
return false;
}
else
{
_balance -= amount;
_todayWithdrawal += amount;
Console.WriteLine($"You have Successfully Withdraw: {amount}");
Console.WriteLine($"Your Account Balance: {_balance}");
return true;
}
}

public decimal CheckBalance()


{
return _balance;
}
}
 CurrentAccount.cs
C#
public class CurrentAccount : IBankAccount
{
private decimal _balance = 0;

public bool DepositAmount(decimal amount)


{
_balance += amount;
Console.WriteLine($"You have Deposited: {amount}");
Console.WriteLine($"Your Account Balance: {_balance}");
return true;
}

public bool WithdrawAmount(decimal amount)


{
if (_balance < amount)
{
Console.WriteLine("You have Insufficient balance!");
return false;
}
else
{
_balance -= amount;
Console.WriteLine($"You have Successfully Withdraw: {amount}");
Console.WriteLine($"Your Account Balance: {_balance}");
return true;
}
}

public decimal CheckBalance()


{
return _balance;
}
}
3. Usage in the Main Method
C#
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Saving Account:");
IBankAccount savingAccount = new SavingAccount();
savingAccount.DepositAmount(2000);
savingAccount.DepositAmount(1000);
savingAccount.WithdrawAmount(1500);
savingAccount.WithdrawAmount(5000);
Console.WriteLine($"Saving Account Balance: {savingAccount.CheckBalance()}");

Console.WriteLine("\nCurrent Account:");
IBankAccount currentAccount = new CurrentAccount();
currentAccount.DepositAmount(500);
currentAccount.DepositAmount(1500);
currentAccount.WithdrawAmount(2600);
currentAccount.WithdrawAmount(1000);
Console.WriteLine($"Current Account Balance: {currentAccount.CheckBalance()}");

Console.ReadLine();
}
}
Key Benefits
 Polymorphism: The IBankAccount interface allows you to treat both SavingAccount and
CurrentAccount objects uniformly.
 Extensibility: You can easily add new account types (e.g., "Fixed Deposit") by creating new
classes that implement the IBankAccount interface.
 Maintainability: Changes to the interface will automatically affect all implementing classes,
ensuring consistency across the system.
Multiple Inheritance in C#
C# does not directly support multiple inheritance for classes. This means a class can only inherit
from one parent class at a time. However, interfaces provide a way to achieve similar functionality.
Why not Multiple Inheritance with Classes?
The primary reason for not allowing multiple inheritance with classes is the ambiguity problem.
Imagine a scenario where two parent classes have methods with the same name and signature.
When inheriting from both classes, the compiler wouldn't know which method implementation to
use, leading to errors.
Interfaces to the Rescue
Interfaces define contracts that classes can implement. A class can implement multiple interfaces,
inheriting their methods and properties without the ambiguity problem. Here's how it works:
 Interfaces only contain method declarations, not implementations.
 Classes implementing an interface must provide implementations for all declared methods.
Benefits of Using Interfaces for Multiple Inheritance
 Flexibility: Classes can inherit behavior from multiple interfaces without conflicts.
 Extensibility: New interfaces can be created without modifying existing classes.
 Loose Coupling: Interfaces promote loose coupling between classes, making code more
maintainable and testable.
Example: Bank Account System
Let's consider a bank account system with different account types (Savings and Current). Here's how
we can use interfaces for multiple inheritance:
1. Define an IBankAccount interface with common functionalities like Deposit, Withdraw, and
CheckBalance.
2. Create separate SavingsAccount and CurrentAccount classes implementing IBankAccount.
3. Each class provides specific implementations for deposit/withdrawal rules based on their
account type.
Code Example
C#
interface IBankAccount
{
bool Deposit(decimal amount);
bool Withdraw(decimal amount);
decimal CheckBalance();
}

class SavingsAccount : IBankAccount


{
private decimal _balance;
private readonly decimal _perDayWithdrawLimit;

public bool Deposit(decimal amount)


{
// Implement deposit logic for Savings Account
}

public bool Withdraw(decimal amount)


{
// Implement withdrawal logic with per-day limit check
}

public decimal CheckBalance()


{
return _balance;
}
}

class CurrentAccount : IBankAccount


{
private decimal _balance;

public bool Deposit(decimal amount)


{
// Implement deposit logic for Current Account
}

public bool Withdraw(decimal amount)


{
// Implement withdrawal logic without any limit check
}

public decimal CheckBalance()


{
return _balance;
}
}
Key Points to Remember
 Interfaces cannot be instantiated.
 A class can implement multiple interfaces.
 Interfaces promote loose coupling and cleaner code design.
Additional Considerations
 While interfaces offer a good alternative to multiple inheritance with classes, there might be
situations where true multiple inheritance is desirable. In such cases, consider using design
patterns like the Favor Composition Over Inheritance principle.
 When using multiple interfaces, ensure there are no conflicting method signatures across
interfaces.
Polymorphism in C#
Polymorphism is a fundamental concept in object-oriented programming (OOP) that allows objects
of different classes to 1 respond differently to the same method call. It literally means "many forms"
and enables code to be more flexible and reusable.

1. github.com

github.com

Types of Polymorphism in C#
There are two main types of polymorphism in C#:
1. Compile-Time Polymorphism (Static Polymorphism, Early Binding):
o The behavior of a method is determined at compile time based on the method
signature (name and number and types of parameters).
o Achieved through method overloading.
o Method overloading allows multiple methods with the same name but different
signatures within the same class.
o The compiler selects the appropriate method based on the arguments used in the
call.
2. Run-Time Polymorphism (Dynamic Polymorphism, Late Binding):
o The behavior of a method is determined at runtime based on the object's actual
type.
o Achieved through inheritance and method overriding.
o A subclass (derived class) can override a method inherited from its parent (base
class) to provide its own implementation.
o When a method is called on a reference variable of the parent class type, the actual
object's type determines which method implementation is executed at runtime.
Benefits of Polymorphism
 Flexibility: Code can adapt to different situations based on the object type.
 Reusability: Methods can be written in a generic way to handle different types of objects.
 Maintainability: Code is easier to understand and modify because the logic is centralized in
methods.
Example: Shape Inheritance
C#
class Shape
{
public virtual void Draw() // Virtual method for overriding
{
Console.WriteLine("Drawing a shape");
}
}
class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a circle");
}
}

class Square : Shape


{
public override void Draw()
{
Console.WriteLine("Drawing a square");
}
}

class Program
{
static void Main(string[] args)
{
Shape[] shapes = { new Circle(), new Square() };
foreach (Shape shape in shapes)
{
shape.Draw(); // Calls the appropriate Draw method based on object type at runtime
}
}
}
Output:
Drawing a circle
Drawing a square
Key Points
 Polymorphism is a powerful tool for writing flexible and reusable code.
 Compile-time polymorphism uses method signatures for binding, while run-time
polymorphism uses object types for binding.
 Inheritance and method overriding are essential for achieving run-time polymorphism.
 Consider using interfaces for alternative inheritance-like behavior without the ambiguity
problem of multiple class inheritance.
Method Overloading in C#
Method overloading is a fundamental concept in object-oriented programming (OOP) that allows you
to define multiple methods with the same name within a class, but with different signatures. The
signature of a method is determined by the number, type, and order of its parameters.
Key Points:
 Allows for cleaner and more intuitive code.
 Improves code readability and maintainability.
 Enables polymorphism (one method name, different behaviors based on arguments).
 Achieved through differences in method signatures, not return types.
Benefits of Method Overloading:
 Flexibility: Code can adapt to different situations based on the arguments provided.
 Reusability: Methods can be written in a generic way to handle various data types.
 Readability: Code becomes more readable as overloaded methods often have clear names
reflecting their purpose.
Example:
C#
class Shape
{
public virtual void Draw() // Virtual method for overriding
{
Console.WriteLine("Drawing a shape");
}
}

class Circle : Shape


{
public override void Draw()
{
Console.WriteLine("Drawing a circle");
}
}

class Square : Shape


{
public override void Draw()
{
Console.WriteLine("Drawing a square");
}
}

class Program
{
static void Main(string[] args)
{
Shape[] shapes = { new Circle(), new Square() };
foreach (Shape shape in shapes)
{
shape.Draw(); // Calls the appropriate Draw method based on object type at runtime
(polymorphism)
}
}
}
Output:
Drawing a circle
Drawing a square
When to Use Method Overloading:
 When you need to perform the same operation on different data types.
 When you want to provide multiple ways to call a method with varying amounts of data.
 To improve code readability by using descriptive method names with overloaded versions for
different scenarios.
Things Not Considered in Method Signature:
 Return Type: While methods can have different return types, it's not part of the signature for
overloading. You cannot overload methods based solely on return type differences.
 Access Specifiers (public, private, protected): These can be different for overloaded
methods.
 Access Modifiers (sealed, static, virtual): These can also be different for overloaded
methods.
Overloading vs. Overriding:
 Overloading: Occurs within the same class, methods have the same name but different
signatures.
 Overriding: Occurs in inheritance hierarchies, a subclass redefines a method inherited from
its parent class.
Additional Notes:
 Method overloading is resolved at compile time.
 C# allows overloading constructors (special methods for object creation) based on parameter
differences.
Method Overriding in C#
Method overriding is a fundamental object-oriented programming (OOP) concept that allows you to
redefine the behavior of an inherited method in a subclass. It enables polymorphism, a cornerstone
of OOP that allows for "one method name, different behaviors based on arguments."
Key Points:
 Redefining Inherited Methods: Subclasses (derived classes) can override methods inherited
from their parent classes (base classes).
 Signature Matching: The overriding method must have the same signature (name,
parameter list) as the overridden method.
 Access Modifiers: Overridden methods can have different access modifiers (public, private,
protected) than the overridden method.
 Virtual Keyword: The parent class method must be declared as virtual to allow overriding in
subclasses.
 override Keyword: The subclass method uses the override keyword to explicitly indicate it's
overriding a parent class method.
 Benefits:
o Flexibility: Code adapts to specific situations based on arguments provided.
o Reusability: Methods are written generically to handle various data types.
o Readability: Clear method names and overriding behavior enhance code clarity.
Diagram:
+--------------+
| Base Class | (Parent)
+--------------+
|
(Inherits) +--------------+
| | Sub Class 1 | (Child 1)
+--------------+ |
| +--------------+
| (Inherits) | Sub Class 2 | (Child 2)
+--------------+ |
+--------------+
| Sub Class N | (Child N)
+--------------+

- Overridden methods can exist in multiple subclasses of the base class.


- Each subclass can potentially have its own implementation of the overridden method.
Code Example:
C#
class Shape
{
public virtual void Draw() // Virtual method for overriding
{
Console.WriteLine("Drawing a shape");
}
}

class Circle : Shape


{
public override void Draw()
{
Console.WriteLine("Drawing a circle");
}
}

class Square : Shape


{
public override void Draw()
{
Console.WriteLine("Drawing a square");
}
}

class Program
{
static void Main(string[] args)
{
Shape[] shapes = { new Circle(), new Square() };
foreach (Shape shape in shapes)
{
shape.Draw(); // Calls the appropriate Draw method based on object type at runtime
(polymorphism)
}
}
}
Output:
Drawing a circle
Drawing a square
Explanation:
1. The Shape class defines a Draw() method declared as virtual. This allows subclasses to
override it.
2. The Circle and Square classes inherit from Shape.
3. Both Circle and Square override the Draw() method with their specific implementation for
drawing a circle and a square, respectively.
4. In the Main() method, an array of Shape objects holds instances of Circle and Square.
5. The foreach loop iterates through the shapes array.
6. When shape.Draw() is called, the runtime determines the actual type of the object (Circle or
Square) and invokes the overridden method defined in that specific subclass. This
demonstrates polymorphism in action.
Key Differences from Method Overloading:
Feature Method Overriding Method Overloading
Signature Same name, same signature Same name, different signature
Location Subclass Same class
Inheritance Required Not required
Keyword override keyword used No special keyword needed
Purpose Redefine inherited behavior Provide multiple functionalities
Polymorphism Enables dynamic polymorphism Enables static polymorphism
Export to Sheets
Additional Notes:
 Method overriding is resolved at runtime.
 C# allows overriding constructors (special methods for object creation) based on parameter
differences.
 Overridden methods can call the overridden method using the base keyword.
Method Hiding in C#
Method Hiding (also known as Shadowing) allows you to redefine a method inherited from a base
class in a derived class, using the same name and signature (name and parameter list). However,
unlike Method Overriding, it's done without explicitly declaring the derived class method as override.
Key Points:
 Redefining Inherited Methods: Derived classes can hide inherited methods from the base
class.
 Signature Matching: The hidden method must have the same signature as the base class
method.
 Access Modifiers: Visibility of the hidden method can be different from the base class
method.
 No virtual or override Keywords: Unlike Overriding, neither virtual nor override keywords
are used.
 Optional new Keyword: While not strictly necessary, using new explicitly clarifies to the
compiler that you intend to hide the base class method.
 Compiler Warning: Without the new keyword, the compiler will issue a warning about hiding
the base class method.
Diagram:
+--------------+
| Base Class | (Parent)
+--------------+
|
(Inherits) +--------------+
| | Derived Class | (Child)
+--------------+
|
| (Hides Methods)
Code Example:
C#
class Shape
{
public void Draw() // Base class method
{
Console.WriteLine("Drawing a shape");
}
}

class Circle : Shape


{
public new void Draw() // Hides the base class Draw method
{
Console.WriteLine("Drawing a circle");
}
}

class Square : Shape


{
public void Draw() // Overrides the base class Draw method (optional)
{
Console.WriteLine("Drawing a square");
}
}

class Program
{
static void Main(string[] args)
{
Shape[] shapes = { new Circle(), new Square() };
foreach (Shape shape in shapes)
{
shape.Draw(); // Calls the appropriate Draw method based on object type
}
}
}
Output:
Drawing a circle
Drawing a square
Explanation:
1. The Shape class defines a Draw() method.
2. The Circle class inherits from Shape.
3. The Circle class defines its own Draw() method with the new keyword, hiding the base class
method.
4. The Square class inherits from Shape and overrides the Draw() method using the override
keyword (optional for non-abstract methods).
5. In the Main() method, an array of Shape objects holds instances of Circle and Square.
6. The foreach loop iterates through the shapes array.
7. When shape.Draw() is called, the runtime determines the actual type of the object (Circle or
Square) and invokes the appropriate hidden or overridden method defined in that specific
subclass.
Key Differences from Method Overriding:
Feature Method Hiding Method Overriding
Signature Same name, same signature Same name, same signature
Location Derived class (without override) Derived class (with override)
Required (base class method must
Inheritance Not required
be virtual)
No special keyword needed (optional
Keyword override keyword used
new)
Purpose Hide base class behavior Redefine base class behavior
Compiler Warning Warning if no new keyword No warning
Accessing Base Class Not directly accessible using derived Can be accessed using base
Method class instance keyword
Export to Sheets
When to Use Method Hiding:
 You don't want the derived class to inherit the base class method behavior but want to keep
the same method name and signature.
 You're working with legacy code where overriding wasn't used consistently.
 You need to explicitly indicate that a method is intended to hide the base class method
(using new).
Considerations:
 Method hiding can make code less readable and maintainable as the base class method is no
longer directly accessible through the derived class instance.
 Overriding is generally preferred as it maintains a clear relationship between base and
derived class methods.
Partial Classes and Partial Methods in C#
Partial Classes
 Concept: Allow you to split the definition of a class across multiple files.
 Syntax: Use the partial keyword before the class declaration in each file.
 Benefits:
o Improved Code Organization: Large classes can be divided into smaller, more
manageable units.
o Collaboration: Multiple developers can work on different parts of a class
simultaneously.
o Code Generation: Useful for code generated by tools like Entity Framework, where
you can add custom logic to auto-generated classes.
Example:
 File 1: Employee.cs
C#
public partial class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
 File 2: Employee.cs
C#
public partial class Employee
{
public double Salary { get; set; }
public void CalculateSalary()
{
// Calculate salary logic
}
}
Partial Methods
 Concept: Allow you to define a method signature without an implementation. The
implementation can be provided in another part of the partial class.
 Syntax:
o Declare the method with the partial keyword and void return type.
o Provide the implementation of the partial method in another part of the partial
class.
 Behavior:
o If the implementation is not provided, the compiler removes the partial method and
all calls to it.
o Useful for optional behavior or code generation scenarios.
Example:
 File 1: MyClass.cs
C#
public partial class MyClass
{
public void DoSomething()
{
Console.WriteLine("Doing something...");
LogEvent(); // Call to the partial method
}

partial void LogEvent(); // Declaration of the partial method


}
 File 2: MyClass.cs
C#
public partial class MyClass
{
partial void LogEvent() // Implementation of the partial method
{
// Log the event to a file or database
Console.WriteLine("Event logged.");
}
}
Rules for Partial Classes:
 All parts must have the same access modifier (e.g., public, private).
 All parts must have the same base class or interface (if any).
 If any part is declared abstract, the entire class is considered abstract.
 If any part is declared sealed, the entire class is considered sealed.
Rules for Partial Methods:
 Must have void return type.
 Cannot have access modifiers, virtual, abstract, override, new, sealed, or extern modifiers.
 Must be declared within a partial class or struct.
 Implementation is optional. If not implemented, the method and its calls are removed by the
compiler.
 Declaration and implementation must have the same signature.
Key Use Cases:
 Large Classes: Splitting large classes into smaller, more manageable files improves readability
and maintainability.
 Code Generation: Useful for working with code generated by tools, allowing you to add
custom logic to auto-generated classes.
 Optional Behavior: Implement optional functionality using partial methods, which can be
removed by the compiler if not needed.
In Summary:
Partial classes and partial methods are powerful features in C# that enhance code organization,
maintainability, and flexibility. By understanding their usage and limitations, you can effectively
leverage these features in your C# applications.
Sealed Classes
 Concept: A sealed class prevents inheritance. You cannot create new classes derived from a
sealed class.
 Purpose:
o Enforce a specific behavior or implementation for a class.
o Prevent unintended modifications through inheritance.
o Improve performance by avoiding virtual method calls (discussed later).
 Syntax: Use the sealed keyword before the class declaration.
C#
public sealed class MathUtils
{
public static double Add(double a, double b)
{
return a + b;
}
}
 Example: In the MathUtils class, the Add method is crucial for calculations, and you want to
ensure its implementation remains unchanged. Sealing the class prevents subclasses from
accidentally overriding it.
Diagram:
Code snippet
graph LR
A[MathUtils (sealed)] --> B{Object usage}
Key Points:
 Sealed classes can still be instantiated and their members accessed.
 They can implement interfaces to define contracts.
 Sealed classes are often used for utility classes, singletons, and base classes where
inheritance is not desired.
Sealed Methods
 Concept: A sealed method prevents overriding in derived classes.
 Purpose:
o Ensure a specific implementation is used throughout the inheritance hierarchy.
o Improve performance by avoiding virtual method call overhead (explained later).
 Syntax: Use the sealed keyword with the override keyword when overriding a virtual method
in a derived class.
C#
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Generic animal sound");
}
}

public class Dog : Animal


{
public sealed override void MakeSound()
{
Console.WriteLine("Woof!");
}
}
 Example: In the Animal hierarchy, the Dog class sound should always be "Woof!". Sealing the
MakeSound method in Dog prevents further subclasses from overriding it.
Diagram:
Code snippet
graph LR
A[Animal] --> B{MakeSound()}
B --> C[Dog (sealed MakeSound())]
C --> D{Object usage}
Key Points:
 A method can only be sealed if it's already declared as virtual in the base class.
 Sealed methods are inherited but cannot be overridden.
 They are often used for core functionalities that shouldn't be altered in subclasses.
Comparison with Related Concepts
 Abstract Classes: Abstract classes define a contract that derived classes must implement.
They cannot be instantiated directly. Sealed classes prevent inheritance, while abstract
classes require inheritance.
 Private Methods: Private methods are hidden within a class and cannot be accessed from
derived classes. Sealed methods can be accessed from derived classes but cannot be
overridden.
When to Use Sealed Classes and Methods
 Use sealed classes when inheritance is not intended and the class implementation should be
final.
 Use sealed methods when a specific behavior needs to be enforced throughout the class
hierarchy.
 Consider performance implications - sealed methods avoid virtual method call overhead,
which can be beneficial in performance-critical scenarios.
In Summary
Sealed classes and methods are powerful tools in C# for controlling inheritance and ensuring specific
behaviors. By understanding their concepts, purposes, and use cases, you can effectively design
robust and maintainable object-oriented code.

You might also like