0% found this document useful (0 votes)
1 views148 pages

Unit 3 .NetUsingC#

The document covers the params keyword in C#, which allows methods to accept a variable number of arguments as a single array parameter, simplifying method overloads. It also outlines Unit 3 topics, including creating DLL files, exception handling, and garbage collection, among others. Additionally, it explains the advantages and disadvantages of DLLs, their types, and the concept of assemblies of multiple versions to avoid conflicts in .NET applications.

Uploaded by

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

Unit 3 .NetUsingC#

The document covers the params keyword in C#, which allows methods to accept a variable number of arguments as a single array parameter, simplifying method overloads. It also outlines Unit 3 topics, including creating DLL files, exception handling, and garbage collection, among others. Additionally, it explains the advantages and disadvantages of DLLs, their types, and the concept of assemblies of multiple versions to avoid conflicts in .NET applications.

Uploaded by

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

params keyword

and unit 3 lets boom

Unit-III Creating DLL files, Assemblies of multiple versions. GAC


Utility and Strong Name, Arrays and Strings, Boxing and Unboxing, –
Exception Handling in C#, Garbage Collection & Its Stages, Files and
Streams, Delegates and their usefulness and Events, Attributes, I/O
in C# and Windows Applications.

6/13/2026, 11:53:52 AM

Great catch — params first, then Unit 3! 👇


📌 Extra: params Keyword
EXAM DEFINITION
The params keyword in C# allows a method to accept a variable number of arguments of
the same type. Instead of defining multiple overloaded methods for different numbers of
arguments, params accepts any number of values as a single array parameter. It must be
the last parameter in the method signature.

WITHOUT params — Problem

// Need separate overloads for different counts — messy!


int Sum(int a, int b) { return a + b; }
int Sum(int a, int b, int c) { return a + b + c; }
int Sum(int a, int b, int c, int d) { return a + b + c + d; }

WITH params — Clean Solution

Powered by Claude Exporter 235/382


int Sum(params int[] numbers) {
int total = 0;
foreach (int n in numbers)
total += n;
return total;
}

// All valid calls:


[Link](Sum(1, 2)); // Output: 3
[Link](Sum(1, 2, 3)); // Output: 6
[Link](Sum(1, 2, 3, 4, 5)); // Output: 15
[Link](Sum()); // Output: 0

RULES
Only one params parameter per method

Must be the last parameter

Must be a single-dimensional array

Can pass zero or more arguments

// With other parameters before params


void Display(string label, params int[] values) {
[Link](label + ": ");
foreach (int v in values)
[Link](v + " ");
[Link]();
}

Display("Scores", 85, 90, 78, 92);


// Output: Scores: 85 90 78 92

⭐ Exam Use
Asked in M-24 Q5b — "different methods to pass arguments"

Powered by Claude Exporter 236/382


Always mention alongside ref and out as the 4th method of argument passing

Now Unit 3! 🔥 Let me map it out first 👇


📋 Unit 3 — Topic Map
# Topic

1 Creating DLL Files

2 Assemblies of Multiple Versions

3 GAC Utility and Strong Name

4 Arrays and Strings

5 Boxing and Unboxing

6 Exception Handling in C#

7 Garbage Collection and Its Stages

8 Files and Streams

9 Delegates and Their Usefulness + Events

10 Attributes

11 I/O in C# and Windows Applications

11 topics!

Quick note — some of these are already partially covered:

GAC + Strong Name → covered in Unit 1 extra topics ✅ (will do quick recap)
Boxing/Unboxing → covered in Unit 2 Topic 6 ✅ (quick recap)
Delegates + Events → covered in Unit 2 Topic 9 ✅ (will expand)

So we go deep on new ones, quick recap on repeated ones!

Ready? Starting Topic 1: Creating DLL Files 🚀


Powered by Claude Exporter 237/382
Just say "go"!
6/13/2026, 11:54:07 AM

Powered by Claude Exporter 238/382


goooo :)

6/13/2026, 11:56:27 AM

📌 Topic 1: Creating DLL Files


EXAM DEFINITION
A DLL (Dynamic Link Library) file is a compiled library file in .NET that contains reusable
code — classes, methods, and resources — that can be shared across multiple applications
without recompiling. Unlike .exe files which are executable, .dll files cannot run
standalone — they must be referenced and used by other applications. In .NET, DLL files are
a type of Assembly containing CIL code and metadata.

CORE CONCEPT
DLL vs EXE

DLL EXE

Full Form Dynamic Link Library Executable

Can run standalone ❌ No ✅ Yes


Purpose Reusable library Application entry point

Entry point No Main() Has Main()

Used by Multiple apps End user directly

Extension .dll .exe

Why DLL?

Without DLL — every application copies the same code:

Powered by Claude Exporter 239/382


App A → has MathHelper code (copy)
App B → has MathHelper code (copy)
App C → has MathHelper code (copy)

→ Code duplication, maintenance nightmare!

With DLL:

App A ──→ [Link] ←── App B



App C

→ One shared library, all apps use it ✅


STEP-BY-STEP: CREATING A DLL IN C#
Step 1 — Create Class Library Project

In Visual Studio:

File → New → Project → Class Library (.NET)

Name it: MathLibrary

Step 2 — Write Library Code

// [Link] — inside MathLibrary project


using System;

namespace MathLibrary {

public class MathHelper {

// Basic arithmetic
public int Add(int a, int b) {
return a + b;
}

Powered by Claude Exporter 240/382


public int Subtract(int a, int b) {
return a - b;
}

public int Multiply(int a, int b) {


return a * b;
}

public double Divide(double a, double b) {


if (b == 0)
throw new DivideByZeroException("Cannot divide by
zero!");
return a / b;
}

// Area calculations
public double CircleArea(double radius) {
return [Link] * radius * radius;
}

public double RectangleArea(double width, double height) {


return width * height;
}
}

public class StringHelper {

public string Reverse(string s) {


char[] chars = [Link]();
[Link](chars);
return new string(chars);
}

public bool IsPalindrome(string s) {


return s == Reverse(s);

Powered by Claude Exporter 241/382


}

public int WordCount(string s) {


return [Link](' ').Length;
}
}
}

Step 3 — Build the DLL

Build → Build Solution

Output: [Link] in bin/Debug or bin/Release folder

This DLL contains CIL code + Metadata — ready to be shared!

Step 4 — Reference DLL in Another Application

In Visual Studio:

Create new Console App project

Right-click References → Add Reference → Browse → select [Link]

Using dotnet CLI:

dotnet add reference ../MathLibrary/[Link]

Step 5 — Use the DLL

// [Link] — in the Console Application


using System;
using MathLibrary; // import the DLL's namespace

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

// Using MathHelper from DLL

Powered by Claude Exporter 242/382


MathHelper math = new MathHelper();
[Link]("Add: " + [Link](10, 5)); // 15
[Link]("Multiply: " + [Link](4, 3)); // 12
[Link]("Circle Area: " + [Link](7)); //
153.93

// Using StringHelper from DLL


StringHelper str = new StringHelper();
[Link]("Reverse: " + [Link]("Hello")); //
olleH
[Link]("Palindrome: " +
[Link]("madam")); // True
[Link]("Words: " + [Link]("Hello World"));
// 2
}
}

Output:

Add: 15
Multiply: 12
Circle Area: 153.938...
Reverse: olleH
Palindrome: True
Words: 2

WHAT'S INSIDE A DLL?

[Link]
├── CIL Code
│ ├── [Link]()
│ ├── [Link]()
│ ├── [Link]()
│ └── ... all methods compiled to CIL
├── Metadata

Powered by Claude Exporter 243/382


│ ├── Class names, method signatures
│ ├── Parameter types, return types
│ └── Assembly version info
└── Manifest
├── Assembly name: MathLibrary
├── Version: [Link]
└── Dependencies list

ICDLL FILES (J-21 Q7b — directly asked!)


ICDLL stands for Incremental Compiler DLL — these are special DLL files used by the .NET
compiler infrastructure. More broadly in exam context, ICDLL refers to:

DLL files created through incremental compilation

Only changed parts of code are recompiled — not the entire project

Significantly speeds up build time for large projects

Stored in obj folder during development as temporary assemblies

Final clean DLL goes to bin folder

Key Points about ICDLL for Exams:

Used internally by Visual Studio build system

Enables faster iterative development

Part of .NET's incremental build system

Not the same as final release DLL — intermediate build artifact

When you do Build → incremental, Rebuild → full fresh compile

TYPES OF DLL IN .NET


1. Private DLL

Used by one application only

Stored in application folder (same directory as .exe )

No registration needed

Powered by Claude Exporter 244/382


Simple xcopy deployment

2. Shared DLL (Strong-Named)

Used by multiple applications

Stored in GAC (Global Assembly Cache)

Requires strong name (digital signature)

Versioning supported

3. Resource DLL (Satellite Assembly)

Contains only resources — images, strings, localization data

No executable code

Used for multilingual applications

ADVANTAGES OF DLL
Code Reusability — Write once, use in many applications

Modular Design — Application split into manageable components

Easy Updates — Update DLL → all apps using it get the update

Memory Efficiency — One DLL loaded in memory, shared by multiple processes

Separation of Concerns — Business logic in DLL, UI in EXE

Team Development — Different teams work on different DLLs independently

DISADVANTAGES OF DLL
DLL Hell — Version conflicts when multiple apps need different versions (solved by GAC)

Dependency — Application fails if DLL missing or corrupted

Debugging — Slightly harder to debug across DLL boundaries

Overhead — Extra indirection vs inline code

FEATURES / CHARACTERISTICS
Contains CIL code + Metadata + Manifest — self-describing

Powered by Claude Exporter 245/382


Language Independent — DLL written in C# usable from [Link] or F#

Versioned — Each DLL has version number in manifest

Secure — Can be strong-named and signed

Reflectable — Can inspect DLL contents at runtime using Reflection

DIAGRAM GUIDANCE
Draw: DLL Usage Diagram

Center box: [Link]

Three boxes pointing TO the DLL with arrows:

Console App → references DLL

Web App → references DLL

WinForms App → references DLL

Label arrows: "references"

Inside DLL box write: CIL Code + Metadata + Manifest

Draw: DLL Creation Flow

Box 1: C# Source Code (.cs)

Arrow → Box 2: C# Compiler ([Link])

Arrow → Box 3: DLL Assembly (.dll)

Arrow → Box 4: Referenced by Application

Arrow → Box 5: CLR loads + JIT compiles

LONG ANSWER WRITING VERSION (14-Mark Ready)


Introduction:
A DLL (Dynamic Link Library) is a compiled .NET assembly that contains reusable classes,
methods, and resources packaged into a .dll file. Unlike executable ( .exe ) files, DLLs
cannot run independently — they are designed to be referenced and used by other
applications. DLLs promote code reusability, modular design, and efficient memory usage
by allowing multiple applications to share a single compiled library.

Powered by Claude Exporter 246/382


DLL vs EXE:
The key difference between a DLL and an EXE is their purpose and executability. An EXE is a
standalone executable with a Main entry point that users run directly. A DLL is a library with
no entry point — it provides functionality to other programs. Both are .NET Assemblies
containing CIL code and metadata.

Creating a DLL:
Creating a DLL in C# involves five steps. First, create a Class Library project in Visual Studio.
Second, write the library code — public classes and methods that will be shared. Third, build
the project to produce the .dll file containing CIL code and metadata. Fourth, reference
the DLL in another application project. Fifth, use the namespace from the DLL with the
using directive and instantiate its classes.

Contents of a DLL:
A DLL assembly contains CIL (compiled intermediate language code), type metadata (class
names, method signatures, parameter types), and a manifest (assembly name, version,
dependencies). This makes DLLs self-describing — the CLR can load and use them without
external configuration files.

Types of DLLs:
DLLs in .NET come in three types. Private DLLs are stored in the application's folder and
used by that application alone. Shared DLLs are stored in the GAC with a strong name and
can be used by multiple applications with version safety. Satellite Assembly DLLs contain
only resources for localization purposes.

ICDLL Files:
ICDLL (Incremental Compiler DLL) files are temporary DLL artifacts generated during
incremental compilation. When only part of the code changes, the build system recompiles
only the changed portions — producing incremental DLLs that speed up development build
times significantly.

Advantages:
DLLs enable code reusability across projects, modular application architecture, efficient
memory usage (one DLL shared by multiple processes), easy updates (update DLL without
redeploying entire application), and team-based parallel development.

Conclusion:
DLL files are fundamental to .NET application architecture. They enable the separation of
reusable business logic from application-specific code, promote modular design, and

Powered by Claude Exporter 247/382


facilitate team development. Through the GAC and strong naming, .NET solves the
traditional DLL versioning problems, making shared DLLs reliable and conflict-free.

⭐ Probable Exam Questions


1. Discuss base class libraries. How is debugging implemented in .NET? (J-21 Q6b)

2. Write short notes on ICDLL files. (J-21 Q7b) ← directly asked

3. What is a DLL? How is a DLL created in C#? Explain with example.

4. Differentiate between DLL and EXE in .NET.

5. Explain types of DLL assemblies in .NET.

Ready for Topic 2: Assemblies of Multiple Versions? 🚀


6/13/2026, 11:57:20 AM

Powered by Claude Exporter 248/382


yes

6/13/2026, 10:01:28 PM

📌 Topic 2: Assemblies of Multiple Versions


EXAM DEFINITION
Assemblies of Multiple Versions refers to the .NET Framework's ability to allow multiple
versions of the same assembly to exist and run simultaneously on the same machine
without conflict. This is called Side-by-Side Execution. Each assembly carries a version
number in its manifest, and the CLR uses this version information to load the exact version
an application requires — eliminating the traditional problem known as "DLL Hell".

CORE CONCEPT
The Problem — DLL Hell (Before .NET)

In traditional Windows development ([Link]):

App A needs MathLib version 1.0

App B needs MathLib version 2.0

Only ONE version could exist on machine at a time

Installing App B overwrites version 1.0 → App A breaks!

This was called DLL Hell — a major Windows development nightmare

The Solution — .NET Versioning

.NET solved this completely:

Both MathLib v1.0 AND MathLib v2.0 can exist simultaneously

App A loads v1.0, App B loads v2.0

Neither breaks the other ✅


Powered by Claude Exporter 249/382
CLR reads version from manifest → loads exactly the right one

ASSEMBLY VERSION NUMBER


Every .NET assembly has a 4-part version number:

[Link]
1 . 0 . 0 . 0

Part Meaning When Changed

Major Breaking changes Incompatible API changes

Minor New features Backward-compatible additions

Build Build number Regular builds

Revision Hotfix/patch Bug fixes, security patches

Setting Version in C#

// [Link]
[assembly: AssemblyVersion("[Link]")]
[assembly: AssemblyFileVersion("[Link]")]
[assembly: AssemblyInformationalVersion("2.1.0")]

Or in modern .csproj file:

<PropertyGroup>
<AssemblyVersion>[Link]</AssemblyVersion>
<FileVersion>[Link]</FileVersion>
<Version>2.1.0</Version>
</PropertyGroup>

SIDE-BY-SIDE EXECUTION
What is it?

Powered by Claude Exporter 250/382


Multiple versions of the same assembly running simultaneously on the same machine —
each application using its own required version.

Machine
├── GAC
│ ├── MathLibrary, Version=[Link] ← App A uses this
│ ├── MathLibrary, Version=[Link] ← App B uses this
│ └── MathLibrary, Version=[Link] ← App C uses this

├── App A → requests v1.0 → CLR loads v1.0 ✅
├── App B → requests v2.0 → CLR loads v2.0 ✅
└── App C → requests v3.1 → CLR loads v3.1 ✅

All three apps running simultaneously — each with their own version — zero conflict!

HOW CLR RESOLVES ASSEMBLY VERSIONS


When an application requests an assembly, CLR follows this process:

Step 1: Application requests assembly


"I need MathLibrary, Version=[Link]"

Step 2: CLR checks application config file
([Link] / [Link])

Step 3: CLR checks machine-wide policy
([Link])

Step 4: CLR checks publisher policy
(from assembly publisher)

Step 5: CLR searches for assembly:
a) Application directory (private)
b) GAC (shared)

Powered by Claude Exporter 251/382


Step 6: CLR loads exact matching version
or throws FileNotFoundException

VERSION REDIRECTION — [Link]


You can redirect an old version request to a newer version using configuration:

<!-- [Link] -->


<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MathLibrary"
publicKeyToken="abc123def456"
culture="neutral" />
<!-- Redirect old v1.0 requests to v2.0 -->
<bindingRedirect oldVersion="[Link]"
newVersion="[Link]" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

This tells CLR: "If anyone asks for v1.0, give them v2.0 instead"

ASSEMBLY IDENTITY — What Makes a Version Unique


In GAC, an assembly is uniquely identified by 4 things:

Name + Version + Culture + PublicKeyToken

Example:

[Link], Version=[Link], Culture=neutral,


PublicKeyToken=b77a5c561934e089
MathLib, Version=[Link], Culture=neutral,
PublicKeyToken=abc123def456

Powered by Claude Exporter 252/382


MathLib, Version=[Link], Culture=neutral,
PublicKeyToken=abc123def456

Same name, different version → both exist in GAC simultaneously ✅


STRONG NAME — Required for Versioning in GAC
For multiple versions to coexist in GAC, assembly must be strong-named:

Strong Name = Name + Version + Culture + Public Key Token

Creating Strong Name:

Step 1 — Generate key pair:

[Link] -k [Link]

Step 2 — Sign assembly in project:

[assembly: AssemblyKeyFile("[Link]")]
[assembly: AssemblyVersion("[Link]")]

Step 3 — Build → strong-named DLL produced

Step 4 — Install in GAC:

gacutil /i [Link]

Now multiple versions of MathLibrary can safely coexist in GAC!

PUBLISHER POLICY
When a DLL publisher releases a new version and wants ALL applications to automatically
use it — they create a Publisher Policy Assembly:

<!-- [Link] -->


<bindingRedirect oldVersion="[Link]-[Link]"
newVersion="[Link]" />

Powered by Claude Exporter 253/382


Packaged as a special assembly installed in GAC

CLR checks publisher policy before loading

Applications automatically redirect to new version

Can be overridden by [Link] if needed

PRIVATE vs SHARED ASSEMBLY VERSIONING


Private Assembly Shared Assembly (GAC)

Location App directory GAC

Versioning Simple — just replace file Full side-by-side support

Strong name Not required Required

Multiple versions One at a time Multiple simultaneously

Config needed No [Link] for redirection

FEATURES / CHARACTERISTICS
Side-by-Side Execution — Multiple versions coexist without conflict

Version Binding — CLR loads exact version specified in manifest

Policy-Based Redirection — [Link] and publisher policy redirect versions

Strong Name Required — For GAC-based versioning and identity

Self-Describing — Version info stored in assembly manifest — no registry needed

Backward Compatibility — Old apps keep working when new versions installed

ADVANTAGES
Eliminates DLL Hell — Multiple versions coexist peacefully

Application Stability — Apps always get their required version

Safe Updates — New version doesn't break existing applications

Flexible Deployment — Private assemblies need no GAC registration

Controlled Migration — Version redirection lets you migrate gradually

Powered by Claude Exporter 254/382


DISADVANTAGES
Storage — Multiple versions take more disk space

Complexity — Managing many versions across many apps gets complex

Strong Name Overhead — Requires key generation and signing process

GAC Management — Admin rights needed for GAC operations

DIAGRAM GUIDANCE
Draw: Side-by-Side Execution Diagram

Draw a large box labeled "Machine"

Inside it draw "GAC" box containing:

MathLib v1.0

MathLib v2.0

MathLib v3.0

Outside GAC but inside Machine draw three app boxes:

App A → arrow → v1.0

App B → arrow → v2.0

App C → arrow → v3.0

Label: "CLR loads correct version per app"

Draw: Version Resolution Flow

Linear flow diagram:

App Request → [Link] check → [Link] → Publisher Policy → GAC/Local →


Load Assembly

LONG ANSWER WRITING VERSION (14-Mark Ready)


Introduction:
Assemblies of Multiple Versions is a core feature of the .NET Framework that allows multiple
versions of the same assembly to coexist and execute simultaneously on the same
machine. This capability, known as side-by-side execution, directly addresses the classic

Powered by Claude Exporter 255/382


Windows problem of DLL Hell — where installing a new version of a shared library would
overwrite the old version and break existing applications.

The Problem — DLL Hell:


Before .NET, Windows applications shared DLL files stored in common system directories.
When a new application installed an updated version of a shared DLL, it would replace the
existing version — causing previously working applications that depended on the old version
to crash or malfunction. This version conflict problem was commonly known as DLL Hell.

The Solution — .NET Assembly Versioning:


.NET solves this through a combination of assembly version numbers, strong names, the
GAC, and side-by-side execution. Every .NET assembly carries a four-part version number in
its manifest: [Link] . This version number, combined with the
assembly name, culture, and public key token, forms a unique identity that the CLR uses to
load the exact required version.

Side-by-Side Execution:
The CLR supports side-by-side execution — multiple versions of an assembly installed in the
GAC simultaneously. When App A requests MathLibrary v1.0 and App B requests
MathLibrary v2.0 , the CLR loads the correct version for each application independently.

Both applications run simultaneously on the same machine without interfering with each
other.

Version Resolution Process:


When an application requests an assembly, the CLR follows a defined resolution sequence. It
first checks the application configuration file ( [Link] ) for binding redirects. It then
checks the machine-wide configuration ( [Link] ). Next it checks the publisher
policy assembly. Finally it searches the application directory and GAC for the matching
version. If found, it loads the assembly; otherwise it throws a FileNotFoundException .

Version Redirection:
Using [Link] , applications can redirect old version requests to newer versions using
<bindingRedirect> elements. Publisher policy assemblies allow DLL publishers to redirect
all applications to a new version automatically, while individual applications can override this
via their own [Link] .

Strong Names:
For assemblies to support multiple versions in the GAC, they must be strong-named —
digitally signed using a public/private key pair generated by [Link] . The public key token

Powered by Claude Exporter 256/382


becomes part of the assembly's unique identity, preventing tampering and enabling reliable
version identification.

Conclusion:
.NET's assembly versioning system represents a complete solution to the DLL Hell problem.
Through version numbers in manifests, strong names, GAC-based side-by-side storage, and
policy-based version redirection, .NET ensures that multiple applications can coexist on the
same machine each using their exact required assembly version — providing stability,
security, and flexibility in application deployment.

⭐ Probable Exam Questions


1. What are assemblies in .NET? How are assemblies defined according to user requirements?
Enumerate types. (M-23 Q3a) ← directly asked

2. Explain side-by-side execution in .NET assemblies.

3. What is DLL Hell? How does .NET solve it using assembly versioning?

4. Explain version redirection using [Link] in .NET.

5. What is a strong name? Why is it required for shared assemblies?

Ready for Topic 3: GAC Utility and Strong Name? 🚀


6/13/2026, 10:02:24 PM

Powered by Claude Exporter 257/382


yes
btw this is tough unit right?!

6/13/2026, 10:21:15 PM

Honestly? Yes and no 😄


Tough parts:

GAC + Strong Name — lots of steps

Files and Streams — many classes to remember

Exception Handling — syntax + hierarchy

Garbage Collection — stages need memorizing

Easy parts:

Boxing/Unboxing — already done ✅


Delegates/Events — already done ✅

Arrays/Strings — you know programming so concepts are familiar

The good news:


PYQs show examiners repeat the same topics — Exception Handling, GC, Files/Streams,
Delegates are the heavy hitters. GAC/Strong Name we already covered in Unit 1 so it's just
revision!

Overall Unit 3 is concept-heavy but very scoreable if you know the key terms and diagrams
💪
Let's go — Topic 3: GAC Utility and Strong Name — this is mostly revision from Unit 1 so it'll
be quick! 👇
📌 Topic 3: GAC Utility and Strong Name
Powered by Claude Exporter 258/382
EXAM DEFINITION
The Global Assembly Cache (GAC) is a machine-wide centralized repository where shared
.NET assemblies are stored so multiple applications can use them simultaneously. The
[Link] tool manages GAC operations. A Strong Name is a unique digital identity
given to an assembly — consisting of its name, version, culture, and public key token —
required before an assembly can be installed in the GAC.

STRONG NAME — Deep Dive


What is a Strong Name?

Strong Name = Assembly Name


+ Version Number
+ Culture Information
+ Public Key Token (digital signature)

Example of a strong-named assembly identity:

MathLibrary, Version=[Link], Culture=neutral,


PublicKeyToken=abc123def456789a

Why Strong Name is Needed

Uniqueness — Two assemblies with same name but different publishers are
distinguishable

Tamper Protection — Any modification to DLL invalidates the signature

Version Safety — Exact version can be identified and loaded

GAC Requirement — Cannot install in GAC without strong name

Creating a Strong Name — Step by Step

Step 1 — Generate Key Pair using [Link]:

[Link] -k [Link]

Generates a .snk file containing public + private key pair

Powered by Claude Exporter 259/382


Private key used to sign; public key embedded in assembly

Step 2 — Sign Assembly in Project:

// [Link]
[assembly: AssemblyKeyFile("[Link]")]
[assembly: AssemblyVersion("[Link]")]
[assembly: AssemblyCulture("")]

Or in .csproj :

<PropertyGroup>
<SignAssembly>true</SignAssembly>

<AssemblyOriginatorKeyFile>[Link]</AssemblyOriginatorKeyFile>
<AssemblyVersion>[Link]</AssemblyVersion>
</PropertyGroup>

Step 3 — Build Project:

Compiler signs the assembly with private key

Public key token embedded in manifest

Output: strongly named [Link]

Step 4 — Verify Strong Name:

[Link] -v [Link]

Output: [Link]: Valid

GAC UTILITY ([Link])


Key Commands

Command Purpose

gacutil /i [Link] Install assembly into GAC

gacutil /u MathLibrary Uninstall assembly from GAC

Powered by Claude Exporter 260/382


Command Purpose

gacutil /l List ALL assemblies in GAC

gacutil /l MathLibrary List specific assembly

gacutil /ungen MathLibrary Uninstall specific version

GAC Location on Disk

.NET Framework: C:\Windows\assembly\


.NET 4.0+: C:\Windows\[Link]\assembly\

Installation Process

Step 1: Create strongly named assembly



Step 2: gacutil /i [Link]

Step 3: GAC verifies strong name signature

Step 4: Assembly copied to GAC folder

Step 5: Multiple apps can now reference it

Removal Process

Step 1: gacutil /u MathLibrary



Step 2: GAC checks if any app currently using it

Step 3: Assembly removed from GAC folder

WHAT TYPES OF ASSEMBLIES GO IN GAC

Powered by Claude Exporter 261/382


✅ Shared assemblies — used by multiple applications
✅ .NET Framework assemblies — ,
[Link] [Link] etc.

✅ Enterprise components — shared business logic DLLs


✅ Third-party libraries — shared utilities
❌ Private assemblies — stay in app folder, NOT in GAC
❌ Unsigned assemblies — must be strong-named first
PRIVATE vs SHARED ASSEMBLY — Quick Table
Private Assembly Shared Assembly

Location App directory GAC

Strong name Not required Required

Used by One app Multiple apps

Versioning Simple replace Side-by-side

Deployment xcopy gacutil /i

Admin rights Not needed Required

STRONG NAME vs DIGITAL SIGNATURE


Examiners sometimes confuse these:

Strong Name Digital Signature (Authenticode)

Purpose Unique identity + tamper detect Publisher trust + authenticity

Tool [Link] [Link]

Certificate Self-generated key pair Certificate Authority (CA)

Stored in Assembly manifest PE header

Required for GAC installation Distribution trust

FEATURES OF GAC
Centralized Storage — One location for all shared assemblies

Powered by Claude Exporter 262/382


Side-by-Side — Multiple versions of same assembly coexist

Tamper Protection — Strong name signature verified on load

No Registration — Unlike COM, no registry entries needed

Version Resolution — CLR picks exact version per application

ADVANTAGES
Eliminates DLL Hell — Versioning conflicts resolved

Security — Tamper-evident assemblies

Efficiency — One copy shared by many apps

Reliability — CLR always loads correct version

DISADVANTAGES
Admin Rights Required — Cannot install without admin access

Complexity — Key generation and signing adds steps

Machine-Specific — GAC is per machine — web farms need separate installs

DIAGRAM GUIDANCE
Draw: Strong Name Creation Flow

Box 1: Source Code + [Link] (version + key file)

Arrow → Box 2: [Link] generates .snk key pair

Arrow → Box 3: C# Compiler signs assembly with private key

Arrow → Box 4: Strongly Named DLL (public key token embedded)

Arrow → Box 5: gacutil /i installs into GAC

Draw: GAC Structure Diagram

Large box: GAC

Inside: multiple assembly boxes with different versions

MathLib v1.0 | MathLib v2.0 | [Link] v4.0

Powered by Claude Exporter 263/382


Three app boxes outside pointing INTO GAC

CLR box between apps and GAC labeled "version resolver"

⭐ Probable Exam Questions


1. Explain GAC utility. Which types of assemblies are installed in GAC? How are they installed and
removed? (M-24 Q6a) ← directly asked

2. Explain GAC utility. (M-23 compulsory) ← directly asked

3. What is a strong name? How is it created? Why is it needed for GAC?

4. Differentiate between private and shared assemblies.

5. What is side-by-side execution? How does GAC support it?

Topics 1-3 done! 🔥


Remaining Unit 3 topics:

Topic 4 — Arrays and Strings

Topic 5 — Boxing and Unboxing (quick recap)

Topic 6 — Exception Handling ⭐


Topic 7 — Garbage Collection ⭐

Topic 8 — Files and Streams ⭐

Topic 9 — Delegates and Events

Topic 10 — Attributes

Topic 11 — I/O in C#

Ready for Topic 4: Arrays and Strings? 🚀


6/13/2026, 10:22:08 PM

Powered by Claude Exporter 264/382


yes sir

6/13/2026, 11:25:12 PM

📌 Topic 4: Arrays and Strings


EXAM DEFINITION
An Array is a fixed-size, ordered collection of elements of the same data type stored in
contiguous memory locations, accessed using an index. A String is an immutable
sequence of Unicode characters represented by the [Link] class in C#. Both arrays
and strings are reference types stored on the heap.

PART A: ARRAYS
Core Concept

Think of an array like a row of lockers:

All lockers same size (same type)

Each locker has a number (index starting from 0)

Fixed number of lockers (fixed size)

Access any locker directly using its number

TYPES OF ARRAYS IN C#
1. Single-Dimensional Array

Most basic — one row of elements.

// Declaration and Initialization


int[] marks = new int[5]; // size 5, default 0s
int[] marks = {85, 90, 78, 92, 88}; // inline initialization
int[] marks = new int[5]{85, 90, 78, 92, 88}; // both

Powered by Claude Exporter 265/382


// Accessing elements
[Link](marks[0]); // 85 (first element)
[Link](marks[4]); // 88 (last element)

// Traversing
for (int i = 0; i < [Link]; i++) {
[Link]("marks[" + i + "] = " + marks[i]);
}

// foreach traversal
foreach (int m in marks) {
[Link](m + " ");
}
// Output: 85 90 78 92 88

2. Multi-Dimensional Array (Rectangular)

Matrix-like structure — rows and columns.

// 2D Array — 3 rows, 4 columns


int[,] matrix = new int[3, 4];

// Inline initialization
int[,] grid = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};

// Accessing elements
[Link](grid[0, 0]); // 1 (row 0, col 0)
[Link](grid[1, 2]); // 7 (row 1, col 2)
[Link](grid[2, 3]); // 12 (row 2, col 3)

Powered by Claude Exporter 266/382


// Traversing 2D array
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
[Link](grid[i, j] + "\t");
}
[Link]();
}

3D Array:

int[,,] cube = new int[3, 3, 3]; // 3D array

3. Jagged Array (Array of Arrays)

Each row can have different length — array of arrays.

// Jagged array — 3 rows, different column sizes


int[][] jagged = new int[3][];
jagged[0] = new int[]{1, 2, 3}; // row 0: 3 elements
jagged[1] = new int[]{4, 5}; // row 1: 2 elements
jagged[2] = new int[]{6, 7, 8, 9, 10}; // row 2: 5 elements

// Accessing
[Link](jagged[0][0]); // 1
[Link](jagged[2][4]); // 10

// Traversing
foreach (int[] row in jagged) {
foreach (int val in row) {
[Link](val + " ");
}
[Link]();
}

Rectangular vs Jagged Array

Powered by Claude Exporter 267/382


Rectangular Jagged

Syntax int[,] int[][]

Row sizes All same Can differ

Memory Contiguous block Array of arrays

Use when Matrix/grid Variable row data

4. Params Array (already covered)

void Sum(params int[] nums) { ... }

ARRAY CLASS METHODS


[Link] provides useful built-in methods:

int[] nums = {5, 3, 8, 1, 9, 2, 7};

// Sort
[Link](nums);
// nums: {1, 2, 3, 5, 7, 8, 9}

// Reverse
[Link](nums);
// nums: {9, 8, 7, 5, 3, 2, 1}

// Search (must be sorted first)


[Link](nums);
int index = [Link](nums, 5);
[Link]("Found at: " + index);

// Copy
int[] copy = new int[7];
[Link](nums, copy, 7);

Powered by Claude Exporter 268/382


// Length
[Link]([Link]); // 7

// Clear (set to defaults)


[Link](nums, 0, [Link]);

PART B: STRINGS
Core Concept

string name = "Tannu";

String is immutable — once created, cannot be modified

Any "modification" creates a new string object

Stored on heap — reference type

Comparison with == compares content (not reference like in Java)

String Immutability

string s = "Hello";
s = s + " World"; // doesn't modify "Hello"
// creates NEW string "Hello World"
// s now points to new string

Old "Hello" stays in memory until GC collects it — inefficient for many concatenations!

STRING METHODS — Complete Reference

string s = "Hello World";

// LENGTH
[Link]([Link]); // 11

// CASE

Powered by Claude Exporter 269/382


[Link]([Link]()); // HELLO WORLD
[Link]([Link]()); // hello world

// SEARCH
[Link]([Link]("World")); // True
[Link]([Link]("Hello")); // True
[Link]([Link]("World")); // True
[Link]([Link]("World")); // 6
[Link]([Link]("l")); // 9

// EXTRACT
[Link]([Link](6)); // World
[Link]([Link](6, 3)); // Wor

// MODIFY (returns new string!)


[Link]([Link]("World", "C#")); // Hello C#
[Link]([Link]()); // removes whitespace
[Link]([Link]()); // removes leading
whitespace
[Link]([Link]()); // removes trailing
whitespace

// SPLIT
string csv = "Tannu,Riya,Aman";
string[] names = [Link](',');
foreach (string n in names)
[Link](n);
// Output: Tannu / Riya / Aman

// JOIN
string joined = [Link]("-", names);
[Link](joined); // Tannu-Riya-Aman

// COMPARE
[Link]([Link]("abc", "abc")); // 0 (equal)

Powered by Claude Exporter 270/382


[Link]([Link]("abc", "xyz")); // negative
[Link]("abc" == "abc"); // True

// FORMAT
string msg = [Link]("Name: {0}, Age: {1}", "Tannu", 21);
[Link](msg); // Name: Tannu, Age: 21

// INTERPOLATION (modern C#)


string name2 = "Tannu";
int age = 21;
[Link]($"Name: {name2}, Age: {age}");

// CHECK EMPTY/NULL
[Link]([Link]("")); // True
[Link]([Link](" ")); // True

// CONVERT TO ARRAY
char[] chars = [Link]();

// PADDING
[Link]("42".PadLeft(5)); // " 42"
[Link]("42".PadRight(5)); // "42 "

STRING vs STRINGBUILDER ⭐ Important!


Problem with String Concatenation in Loop

string result = "";


for (int i = 0; i < 10000; i++) {
result += [Link](); // creates 10000 new string objects!
}
// Very slow and memory-wasteful!

Solution — StringBuilder (Mutable String)

Powered by Claude Exporter 271/382


using [Link];

StringBuilder sb = new StringBuilder();


for (int i = 0; i < 10000; i++) {
[Link]([Link]()); // modifies same object — no new
objects!
}
string result = [Link]();
// Much faster!

StringBuilder Methods

StringBuilder sb = new StringBuilder("Hello");

[Link](" World"); // Hello World


[Link](" New Line"); // appends + newline
[Link](5, ","); // Hello, World
[Link](5, 1); // Hello World
[Link]("World", "C#"); // Hello C#
[Link](); // empty

[Link]([Link]); // current length


[Link]([Link]()); // convert to string

String vs StringBuilder

String StringBuilder

Mutability Immutable Mutable

Namespace System [Link]

Memory New object per change Same object modified

Performance Slow for many changes Fast for many changes

Thread safety Thread-safe Not thread-safe

Powered by Claude Exporter 272/382


String StringBuilder

Use when Few modifications Many/loop modifications

Methods Rich string methods Append, Insert, Remove

STRING CONVERSION METHODS

// String to other types


int n = [Link]("42");
double d = [Link]("3.14");
bool b = [Link]("true");

// Safe conversion (no exception)


int result;
bool success = [Link]("abc", out result);
[Link](success); // False — "abc" not a number

// Other types to string


string s1 = [Link]();
string s2 = [Link]();
string s3 = [Link](true);

VERBATIM STRING
Ignore escape characters using @ :

// Normal string — need \\ for backslash


string path1 = "C:\\Users\\Tannu\\Documents";

// Verbatim string — use \ directly


string path2 = @"C:\Users\Tannu\Documents";

// Multi-line verbatim string


string multiLine = @"Line 1

Powered by Claude Exporter 273/382


Line 2
Line 3";

ESCAPE SEQUENCES IN STRINGS


Sequence Meaning

\n New line

\t Tab

\\ Backslash

\" Double quote

\r Carriage return

\0 Null character

FEATURES / CHARACTERISTICS
Arrays — Fixed size, same type, index-based, zero-indexed, reference type

Strings — Immutable, Unicode, rich methods, reference type with value comparison

StringBuilder — Mutable, efficient for string building in loops

[Link]/Search — Built-in algorithms via [Link] class

DIAGRAM GUIDANCE
Draw: Array Memory Diagram

Draw a horizontal row of boxes labeled [0] , [1] , [2] , [3] , [4]

Inside each box write values: 85 , 90 , 78 , 92 , 88

Label: "int[] marks — contiguous memory"

Arrow from variable marks on stack → first box on heap

Draw: 2D Array Grid

Draw a 3×4 grid with row/column indices

Powered by Claude Exporter 274/382


Fill with values

Show grid[1,2] pointing to specific cell

Draw: String vs StringBuilder

Left side (String): each concatenation creates new object — show chain of boxes

Right side (StringBuilder): one box that keeps growing — show single expanding box

LONG ANSWER WRITING VERSION (14-Mark Ready)


Introduction:
Arrays and Strings are fundamental data structures in C#. An array is a fixed-size collection
of same-type elements stored in contiguous memory, accessed via zero-based indices. A
string is an immutable sequence of Unicode characters provided by the [Link]
class. Both are reference types stored on the heap.

Types of Arrays:
C# supports three types of arrays. Single-dimensional arrays store elements in a linear
sequence — declared as int[] marks = new int[5] . Multi-dimensional arrays store data
in matrix form — declared as int[,] grid = new int[3,4] — all rows have equal column
count. Jagged arrays are arrays of arrays where each row can have different length —
declared as int[][] jagged = new int[3][] . The [Link] class provides built-in
methods like Sort() , Reverse() , BinarySearch() , and Copy() for array manipulation.

Strings:
Strings in C# are immutable — any modification creates a new string object rather than
modifying the existing one. The [Link] class provides rich methods including
Length , ToUpper() , ToLower() , Contains() , IndexOf() , Substring() , Replace() ,
Split() , Join() , Trim() , and Format() . String comparison using == compares content
in C#. String interpolation using $"Name: {name}" provides clean, readable string
formatting.

StringBuilder:
For scenarios requiring frequent string modifications — especially in loops —
[Link] is preferred over string . Unlike string , StringBuilder is
mutable — it modifies the same object in memory rather than creating new objects. This
makes it significantly faster and more memory-efficient for building strings incrementally.
Key methods include Append() , Insert() , Remove() , Replace() , and Clear() .

Powered by Claude Exporter 275/382


String Conversions:
C# provides multiple conversion mechanisms. [Link]() converts string to integer
throwing exception on failure. [Link]() safely converts returning false without
exception. ToString() converts any type to string. The Convert class provides
comprehensive type conversion utilities.

Conclusion:
Arrays provide efficient indexed access to fixed collections of same-type data, while strings
provide rich text manipulation capabilities. Understanding the immutability of strings and
the performance advantage of StringBuilder is essential for writing efficient C# applications.
Together, arrays and strings form the backbone of data handling in virtually every C#
program.

⭐ Probable Exam Questions


1. Explain files and streams... arrays and strings with example. (M-23 Q6b) ← directly asked

2. Explain arrays in C#. What are the types of arrays?

3. Differentiate between String and StringBuilder in C#.

4. Write a C# program to demonstrate single and multi-dimensional arrays.

5. Explain important string methods in C# with examples.

6. What is a jagged array? How is it different from a rectangular array?

Ready for Topic 5: Boxing and Unboxing (quick recap!) 🚀


6/13/2026, 11:26:13 PM

Powered by Claude Exporter 276/382


yes

6/13/2026, 11:56:44 PM

📌 Topic 5: Boxing and Unboxing (Quick Recap)


EXAM DEFINITION
Boxing is the process of converting a value type (stored on stack) to an object reference
type (stored on heap) implicitly. Unboxing is the reverse process — converting an object
reference type back to a value type explicitly using a cast. Together they allow value types
to be treated as objects in C#'s unified type system.

BOXING

// Value type on stack


int num = 42;

// BOXING — implicit, automatic


object obj = num; // int → object
// CLR:
// 1. Allocates memory on heap
// 2. Copies value 42 to heap
// 3. obj holds reference to heap object

[Link](obj); // Output: 42

What happens internally:

BEFORE BOXING: AFTER BOXING:


Stack Heap Stack Heap

Powered by Claude Exporter 277/382


[42] [ref] ───→ [42]
num obj (object)

UNBOXING

// Unboxing — EXPLICIT cast required


object obj = 42; // boxing
int num = (int)obj; // UNBOXING — explicit cast

[Link](num); // Output: 42

Wrong Type Cast — Exception!

object obj = 42; // int boxed


double d = (double)obj; // ❌ InvalidCastException!
// was int, cannot unbox as double

// Safe unboxing:
if (obj is int) {
int n = (int)obj; // ✅ safe
}

COMPLETE EXAMPLE

// Boxing
int x = 100;
object boxed = x; // boxing — implicit

// Modify original — doesn't affect boxed!


x = 200;
[Link](x); // 200
[Link](boxed); // 100 — independent copy!

// Unboxing

Powered by Claude Exporter 278/382


int unboxed = (int)boxed;
[Link](unboxed); // 100

WHERE BOXING HAPPENS AUTOMATICALLY

// ArrayList stores objects — boxes all value types!


ArrayList list = new ArrayList();
[Link](10); // boxing int → object
[Link](3.14); // boxing double → object
[Link](true); // boxing bool → object

int val = (int)list[0]; // unboxing

PERFORMANCE IMPACT

// BAD — boxing in loop = very slow!


ArrayList list = new ArrayList();
for (int i = 0; i < 100000; i++) {
[Link](i); // 100000 boxing operations!
}

// GOOD — generics avoid boxing completely!


List<int> list = new List<int>();
for (int i = 0; i < 100000; i++) {
[Link](i); // no boxing — stored as int directly!
}

BOXING vs UNBOXING — Summary Table


Boxing Unboxing

Direction Value type → Object Object → Value type

Conversion Implicit (automatic) Explicit (manual cast)

Memory Allocates on heap Copies back to stack

Powered by Claude Exporter 279/382


Boxing Unboxing

Exception risk None InvalidCastException if wrong type

Performance cost Memory allocation Type checking + copy

Example object o = 42; int n = (int)o;

AVOIDING BOXING — USE GENERICS!


Instead of Use

ArrayList List<T>

Hashtable Dictionary<K,V>

Stack Stack<T>

Queue Queue<T>

Generics are type-safe and boxing-free — always prefer them!

DIAGRAM GUIDANCE
Draw: Boxing/Unboxing Memory Diagram

Two zones: Stack (left) and Heap (right)

Boxing: value 42 on stack → arrow labeled "implicit" → object box on heap

Unboxing: object box on heap → arrow labeled "explicit cast" → value 42 on stack

Show reference variable pointing to heap object

⭐ Probable Exam Questions


1. What is boxing and unboxing in C#? Explain with justified example. (M-24 Q6b) ← directly
asked

2. Explain the term unboxing in C#. (M-24 compulsory) ← directly asked

3. Discuss briefly boxing and unboxing. (J-21 compulsory) ← directly asked

4. How do generics help avoid boxing overhead?

Powered by Claude Exporter 280/382


Asked in ALL THREE papers — make sure you nail this topic! 🎯
Ready for Topic 6: Exception Handling — one of the heaviest hitters of Unit 3! ⭐🚀
6/13/2026, 11:57:10 PM

Powered by Claude Exporter 281/382


yes :(

6/14/2026, 12:00:56 AM

😄 don't worry — exception handling is actually very structured


Haha the sad face says it all
and logical once you see the full picture! Let's make it easy 💪

📌 Topic 6: Exception Handling in C#


EXAM DEFINITION
Exception Handling is a mechanism in C# to detect, handle, and recover from runtime
errors gracefully without crashing the program. An Exception is an unexpected event that
occurs during program execution — such as dividing by zero, accessing null reference, or file
not found. C# provides a structured exception handling model using try, catch, finally, and
throw keywords.

WHY EXCEPTION HANDLING?


Without exception handling:

int a = 10, b = 0;
int result = a / b; // Program CRASHES!
[Link]("This never prints");

With exception handling:

try {
int result = a / b;
} catch (DivideByZeroException ex) {
[Link]("Error: " + [Link]);
}
[Link]("Program continues normally!");

Powered by Claude Exporter 282/382


// Output: Error: Attempted to divide by zero.
// Program continues normally!

EXCEPTION HIERARCHY ⭐ Most Important!


[Link]
└── [Link] ← Base of ALL exceptions
├── [Link] ← Runtime/system errors
│ ├── DivideByZeroException
│ ├── NullReferenceException
│ ├── IndexOutOfRangeException
│ ├── StackOverflowException
│ ├── OutOfMemoryException
│ ├── InvalidCastException
│ ├── OverflowException
│ └── FormatException

└── [Link] ← Application-level
errors
└── (User-defined exceptions go here)

THE 4 KEYWORDS
1. try

try {
// Code that MIGHT throw an exception
// Risky code goes here
}

Contains code that may cause exception

Must be followed by at least one catch or finally

2. catch

Powered by Claude Exporter 283/382


catch (ExceptionType variableName) {
// Handle the exception
}

Catches specific exception type

Multiple catch blocks allowed

Most specific exception first!

3. finally

finally {
// Always executes — exception or not!
// Cleanup code goes here
}

Always runs — whether exception occurred or not

Used for cleanup: close files, release connections

Cannot be skipped even with return in try

4. throw

throw new ExceptionType("message");

Manually throws an exception

Can throw built-in or custom exceptions

Can re-throw caught exception: throw;

COMPLETE SYNTAX

try {
// risky code
}

Powered by Claude Exporter 284/382


catch (SpecificException ex) {
// handle specific exception
}
catch (AnotherException ex) {
// handle another exception
}
catch (Exception ex) {
// handle any other exception (general — must be LAST)
}
finally {
// always runs — cleanup
}

COMMON EXCEPTIONS WITH EXAMPLES


1. DivideByZeroException

try {
int a = 10, b = 0;
int result = a / b;
} catch (DivideByZeroException ex) {
[Link]("Cannot divide by zero!");
[Link]("Message: " + [Link]);
}

2. NullReferenceException

try {
string s = null;
[Link]([Link]); // null reference!
} catch (NullReferenceException ex) {
[Link]("Object is null!");
}

Powered by Claude Exporter 285/382


3. IndexOutOfRangeException

try {
int[] arr = {1, 2, 3};
[Link](arr[10]); // index 10 doesn't exist!
} catch (IndexOutOfRangeException ex) {
[Link]("Index out of range!");
}

4. FormatException

try {
int n = [Link]("abc"); // "abc" not a number!
} catch (FormatException ex) {
[Link]("Invalid format!");
}

5. InvalidCastException

try {
object obj = "Hello";
int n = (int)obj; // string cannot cast to int!
} catch (InvalidCastException ex) {
[Link]("Invalid cast!");
}

MULTIPLE CATCH BLOCKS


Order matters — most specific first, most general last:

try {
int[] arr = new int[5];
arr[10] = 100;
int x = 10 / 0;

Powered by Claude Exporter 286/382


}
catch (IndexOutOfRangeException ex) {
// Most specific — caught first if index error
[Link]("Index error: " + [Link]);
}
catch (DivideByZeroException ex) {
// Specific
[Link]("Division error: " + [Link]);
}
catch (SystemException ex) {
// Less specific
[Link]("System error: " + [Link]);
}
catch (Exception ex) {
// Most general — MUST be last!
[Link]("General error: " + [Link]);
}
finally {
[Link]("Cleanup done!");
}

FINALLY BLOCK — Always Executes!

static void ReadFile() {


StreamReader reader = null;
try {
reader = new StreamReader("[Link]");
string content = [Link]();
[Link](content);
}
catch (FileNotFoundException ex) {
[Link]("File not found: " + [Link]);
}
finally {
// This ALWAYS runs — file always gets closed!

Powered by Claude Exporter 287/382


if (reader != null)
[Link]();
[Link]("File closed in finally");
}
}

Even if exception occurs — finally closes the file! ✅


THROW KEYWORD
Throwing Built-in Exception

void Withdraw(double amount) {


if (amount <= 0)
throw new ArgumentException("Amount must be positive!");
if (amount > balance)
throw new InvalidOperationException("Insufficient funds!");
balance -= amount;
}

Re-throwing Exception

try {
int x = [Link]("abc");
}
catch (FormatException ex) {
[Link]("Logging error: " + [Link]);
throw; // re-throws same exception up the call stack
}

CUSTOM EXCEPTIONS ⭐
Create your own exception class by inheriting from Exception :

// Custom exception
class InsufficientFundsException : Exception {

Powered by Claude Exporter 288/382


double amount;

public InsufficientFundsException(double amt)


: base("Insufficient funds! Need: ₹" + amt) {
amount = amt;
}

public double Amount {


get { return amount; }
}
}

// Using custom exception


class BankAccount {
double balance = 5000;

public void Withdraw(double amount) {


if (amount > balance)
throw new InsufficientFundsException(amount - balance);
balance -= amount;
}
}

// Handling custom exception


class Program {
static void Main() {
BankAccount acc = new BankAccount();
try {
[Link](8000);
}
catch (InsufficientFundsException ex) {
[Link]([Link]);
[Link]("Short by: ₹" + [Link]);
}
}

Powered by Claude Exporter 289/382


}
// Output:
// Insufficient funds! Need: ₹3000
// Short by: ₹3000

EXCEPTION PROPERTIES
Every exception object has these properties:

Property Description Example

Message Human-readable error description "Attempted to divide by zero"

StackTrace Call stack at point of exception at [Link]() line 10

Source Assembly that caused exception "ConsoleApp1"

InnerException Wrapped original exception null or original exception

HelpLink URL to help page Usually null

catch (Exception ex) {


[Link]("Message: " + [Link]);
[Link]("Source: " + [Link]);
[Link]("StackTrace: " + [Link]);
}

NESTED TRY-CATCH

try {
[Link]("Outer try");
try {
int x = 10 / 0; // throws here
}
catch (DivideByZeroException ex) {
[Link]("Inner catch: " + [Link]);
throw; // re-throw to outer catch

Powered by Claude Exporter 290/382


}
}
catch (Exception ex) {
[Link]("Outer catch: " + [Link]);
}
finally {
[Link]("Outer finally");
}

Output:

Outer try
Inner catch: Attempted to divide by zero.
Outer catch: Attempted to divide by zero.
Outer finally

EXCEPTION HANDLING FLOW DIAGRAM

Program Execution

try block

Exception occurs?
↙ ↘
YES NO
↓ ↓
catch block continue
↓ ↓
finally finally
block block
↓ ↓
Program Program
continues continues

Powered by Claude Exporter 291/382


FEATURES / CHARACTERISTICS
Structured — try/catch/finally provides clean, readable error handling

Hierarchical — Exception class hierarchy allows catching at different levels

Propagation — Uncaught exceptions bubble up the call stack

Custom — User-defined exceptions for application-specific errors

Finally Guarantee — finally block always executes — guaranteed cleanup

Multiple Catch — Different exceptions handled differently in same try block

ADVANTAGES
Program Stability — Prevents crashes — program handles errors gracefully

Separation of Concerns — Normal code in try, error code in catch

Meaningful Messages — Users see helpful error messages not cryptic crashes

Resource Safety — finally ensures resources always released

Debugging — StackTrace helps pinpoint exact error location

DISADVANTAGES
Performance — Exception handling has overhead — don't use for flow control

Overuse — Catching Exception blindly hides bugs

Silent Failures — Empty catch blocks hide errors dangerously

DIAGRAM GUIDANCE
Draw: Exception Handling Flow

Draw flowchart:

Box: try block executes

Diamond: Exception thrown?

YES → Box: Matching catch block → Box: finally block

NO → Box: finally block

Both paths → Box: Program continues

Powered by Claude Exporter 292/382


Draw: Exception Hierarchy

Tree diagram starting from [Link]

Two branches: SystemException and ApplicationException

Show common exceptions under SystemException

LONG ANSWER WRITING VERSION (14-Mark Ready)


Introduction:
Exception handling in C# is a structured mechanism to detect, handle, and recover from
runtime errors gracefully. An exception is an unexpected event during execution — such as
division by zero, null reference access, or file not found — that disrupts normal program
flow. C# provides four keywords — try, catch, finally, and throw — to implement a robust
exception handling model.

The try Block:


The try block contains code that may potentially throw an exception. When an exception
occurs inside a try block, execution immediately transfers to the matching catch block — any
remaining code in try is skipped.

The catch Block:


The catch block handles a specific type of exception. Multiple catch blocks can follow a
single try — each handling a different exception type. They must be ordered from most
specific to most general — a general Exception catch must always be last. The exception
object provides Message , StackTrace , Source , and InnerException properties for
detailed error information.

The finally Block:


The finally block always executes regardless of whether an exception occurred — making
it ideal for cleanup code like closing files or database connections. Even a return statement
in try cannot prevent finally from executing.

The throw Keyword:


The throw keyword manually raises an exception — either a built-in type like
DivideByZeroException or a custom exception. Using throw; without arguments re-
throws the current exception preserving its original stack trace.

Exception Hierarchy:
All exceptions inherit from [Link] . Runtime errors like DivideByZeroException ,

Powered by Claude Exporter 293/382


NullReferenceException , and IndexOutOfRangeException inherit from SystemException .

Application-specific errors inherit from ApplicationException . Custom exceptions are


created by inheriting from Exception and adding custom properties and messages.

Custom Exceptions:
Developers can create custom exception classes by inheriting from Exception . This allows
application-specific error conditions to be represented as strongly-typed exceptions with
custom messages and properties — caught and handled separately from built-in exceptions.

Conclusion:
Exception handling is essential for building robust, production-quality C# applications. The
try-catch-finally model provides clean separation between normal logic and error handling,
the exception hierarchy enables precise error classification, and custom exceptions allow
meaningful domain-specific error reporting. Proper exception handling prevents crashes,
ensures resource cleanup, and provides meaningful feedback to users and developers alike.

⭐ Probable Exam Questions


1. Write a program in C# for exception handling. (J-21 Q6a) ← directly asked

2. What is Exception? Explain throw, try and catch with example. (M-23 Q7b) ← directly asked

3. What is Exception? Explain various methods of exception handling in C# with code. (M-24
Q7a) ← directly asked

4. Explain catch and throw exception. (M-23 compulsory) ← directly asked

5. Write a C# program demonstrating custom exception handling.

6. Explain the Exception class hierarchy in C#.

7. What is the role of finally block in exception handling?

🎯
Asked in ALL THREE papers — this is THE most important topic of Unit 3!

Don't worry about it being tough — you now have everything you need 😄💪

Ready for Topic 7: Garbage Collection and Its Stages? 🚀


6/14/2026, 12:01:56 AM

Powered by Claude Exporter 294/382


yes u am ready

6/14/2026, 9:22:05 AM

📌 Topic 7: Garbage Collection and Its Stages


EXAM DEFINITION
Garbage Collection (GC) is an automatic memory management feature of the .NET CLR that
identifies and reclaims memory occupied by objects that are no longer referenced by
the application. It eliminates the need for manual memory management (like free() in C or
delete in C++), preventing memory leaks and dangling pointer errors. The .NET GC uses a
generational collection model for efficient memory management.

CORE CONCEPT
Why GC is Needed

In unmanaged languages (C, C++):

int* ptr = new int(42); // allocate


// ... use ptr ...
delete ptr; // MUST manually free!
// forgot to delete? → memory leak!
// deleted twice? → crash!
// use after delete? → undefined behavior!

In C# with GC:

int[] arr = new int[1000]; // allocate


// ... use arr ...
// arr goes out of scope
// GC automatically reclaims memory — no leaks! ✅

Powered by Claude Exporter 295/382


HOW GC WORKS — The Process
Step 1: Marking Phase

GC starts from roots — static fields, local variables, CPU registers

Traverses all object references from roots

Marks every reachable object as alive

Unmarked objects = garbage (no references pointing to them)

Roots → Object A → Object B → Object C (all marked ALIVE)


Object D (not reachable — GARBAGE)
Object E (not reachable — GARBAGE)

Step 2: Relocating Phase

GC compacts the heap by moving live objects together

Updates all references to point to new locations

Eliminates memory fragmentation

Step 3: Compacting Phase

Dead objects' memory reclaimed

Live objects packed to one end of heap

Free memory available as contiguous block

BEFORE GC: AFTER GC:


[A][D][B][E][C][ free ] [A][B][C][ free ]
dead dead (more contiguous free space!)

GENERATIONAL COLLECTION ⭐ Most Important!


.NET GC uses 3 generations — the key insight:

"Most objects die young" — most objects are short-lived (local variables, temp objects)

Powered by Claude Exporter 296/382


So GC focuses most on young objects — very efficient!

Generation 0 (Gen 0) — Youngest

Newly created objects go here

Collected most frequently — runs constantly

Most objects die here — cheap and fast collection

Small size — fills up quickly → triggers Gen 0 GC

// These objects start in Gen 0:


string temp = "temporary";
int[] buffer = new int[10];
// After use — collected in Gen 0 GC

Generation 1 (Gen 1) — Middle Age

Objects that survived one Gen 0 collection

Acts as buffer between Gen 0 and Gen 2

Collected less frequently than Gen 0

If survives Gen 1 GC → promoted to Gen 2

Generation 2 (Gen 2) — Oldest

Objects that survived Gen 1 collection

Long-lived objects — static fields, application-level objects

Collected least frequently — most expensive GC

Also called Full GC when Gen 2 is collected

Object Created → Gen 0 → (survives) → Gen 1 → (survives) → Gen 2


↓ (dies) ↓ (dies) ↓ (dies
eventually)
Collected Collected Collected
(frequent) (less often) (rarely)

Powered by Claude Exporter 297/382


GC GENERATIONS DIAGRAM

Heap Memory
┌─────────────────────────────────────────────────┐
│ Gen 0 │ Gen 1 │ Gen 2 │
│ (new objects) │ (medium) │ (long-lived) │
│ [A][B][C][D] │ [E][F] │ [G][H][I] │
│ ↑ collected │ ↑ less │ ↑ rarely │
│ very often │ often │ collected │
└─────────────────────────────────────────────────┘
↑ ↑ ↑
Gen 0 GC Gen 1 GC Gen 2 GC
(most frequent) (Full GC — rarest)

LARGE OBJECT HEAP (LOH)


Objects larger than 85,000 bytes go directly to the Large Object Heap:

Not compacted (too expensive to move large objects)

Collected only during Gen 2 (Full GC)

Examples: large arrays, big datasets

GC STAGES IN DETAIL ⭐
Examiners often ask specifically about stages:

Stage 1 — Suspension

CLR suspends all managed threads temporarily

Prevents objects from changing while GC runs

Called "Stop the World" pause

Stage 2 — Mark

GC traverses object graph from roots

Marks all reachable (live) objects

Powered by Claude Exporter 298/382


Unreachable objects identified as garbage

Stage 3 — Sweep/Compact

Dead objects' memory reclaimed

Live objects moved together (compaction)

Heap pointer reset to end of live objects

Fragmentation eliminated

Stage 4 — Resume

All suspended threads resume

Application continues execution

New allocations use newly freed memory

FINALIZATION
When GC is about to collect an object with a destructor ( ~ClassName ), it doesn't
immediately collect it:

class ResourceHolder {
~ResourceHolder() {
// Finalizer — called by GC before collection
[Link]("Cleaning up unmanaged resources");
// Release file handles, DB connections etc.
}
}

Finalization Queue Process:

Object unreachable

Has destructor? → YES → Moved to Finalization Queue
↓ ↓
NO Finalizer thread runs destructor

Powered by Claude Exporter 299/382


↓ ↓
Collected immediately Object collected in NEXT GC cycle

Note: Objects with finalizers survive one extra GC cycle — slight performance cost!

IDisposable AND using STATEMENT


For deterministic cleanup (don't wait for GC) — use IDisposable :

class DatabaseConnection : IDisposable {


bool disposed = false;

public void Query() {


[Link]("Running query...");
}

public void Dispose() {


if (!disposed) {
[Link]("Closing DB connection");
disposed = true;
}
}
}

// using statement — automatically calls Dispose()!


using (DatabaseConnection conn = new DatabaseConnection()) {
[Link]();
} // ← Dispose() called automatically here even if exception!

// Output:
// Running query...
// Closing DB connection

using statement = automatic Dispose() call = deterministic cleanup ✅


MANUAL GC INTERACTION

Powered by Claude Exporter 300/382


Developers can interact with GC (though rarely needed):

// Force GC (not recommended in production!)


[Link]();

// Force GC of specific generation


[Link](0); // Gen 0 only
[Link](1); // Gen 0 and Gen 1
[Link](2); // Full GC

// Wait for finalizers to complete


[Link]();

// Get generation of an object


int gen = [Link](myObject);
[Link]("Object is in Gen: " + gen);

// Get total memory used


long memory = [Link](false);
[Link]("Memory used: " + memory + " bytes");

// Suppress finalization (when manually disposed)


[Link](this);

ADVANTAGES OF GC
No Memory Leaks — GC automatically reclaims unused memory

No Dangling Pointers — Objects not freed while still referenced

Developer Productivity — No manual memory management code

Heap Compaction — Eliminates fragmentation

Generational Efficiency — Short-lived objects collected cheaply

DISADVANTAGES OF GC
Non-Deterministic — Developer cannot predict exactly when GC runs

Powered by Claude Exporter 301/382


Pause Time — "Stop the World" pauses can affect performance

Overhead — GC itself consumes CPU time

Finalization Delay — Objects with finalizers take two GC cycles to collect

Not Suitable — Real-time systems cannot tolerate GC pauses

FEATURES / CHARACTERISTICS
Automatic — No manual free() needed

Generational — 3 generations for efficiency

Compacting — Eliminates heap fragmentation

Concurrent — Background GC minimizes pauses in modern .NET

Configurable — Server GC vs Workstation GC modes

Finalization Support — Calls destructors before collection

DIAGRAM GUIDANCE
Draw: Generational GC Diagram

Draw heap as horizontal rectangle

Divide into 3 sections: Gen 0 (small, left), Gen 1 (medium, middle), Gen 2 (large, right)

Show arrows: new objects enter Gen 0

Show promotion arrows: Gen 0 → Gen 1 → Gen 2 (survivors)

Show collection arrows pointing DOWN from each generation (downward =


collected/dead)

Label frequency: Gen 0 (most frequent), Gen 1 (less), Gen 2 (least)

Draw: GC Stages Flow

4 boxes in sequence:

Suspend Threads → Mark Live Objects → Sweep/Compact → Resume Threads

Arrow loop back from Resume → application runs → Suspend (next GC cycle)

LONG ANSWER WRITING VERSION (14-Mark Ready)

Powered by Claude Exporter 302/382


Introduction:
Garbage Collection (GC) is the automatic memory management system of the .NET CLR. It
identifies objects in heap memory that are no longer referenced by the application and
reclaims their memory — eliminating memory leaks and dangling pointer errors that plague
unmanaged languages like C and C++. The .NET GC uses a sophisticated generational
model to maximize efficiency.

How GC Works:
The GC process involves four stages. In the Suspension stage, all managed application
threads are briefly paused to prevent the object graph from changing during collection. In
the Mark stage, the GC traverses the object reference graph starting from roots (static
fields, local variables, CPU registers) and marks every reachable object as live. Unreachable
objects are identified as garbage. In the Sweep/Compact stage, dead objects' memory is
reclaimed and live objects are compacted together, eliminating heap fragmentation. In the
Resume stage, application threads are released and execution continues.

Generational Collection:
The .NET GC uses three generations based on the observation that most objects are short-
lived. Generation 0 holds newly created objects and is collected most frequently — most
objects die here cheaply. Generation 1 holds objects that survived one Gen 0 collection — it
acts as a buffer. Generation 2 holds long-lived objects like static fields and application-level
data — collected least frequently in what is called a Full GC. Objects surviving collection in
one generation are promoted to the next.

Large Object Heap:


Objects larger than 85,000 bytes are allocated on the Large Object Heap (LOH) rather than
the generational heap. LOH is collected during Gen 2 GC and is typically not compacted due
to the cost of moving large objects.

Finalization:
Objects with destructors ( ~ClassName ) are placed in a finalization queue when they become
unreachable. A dedicated finalizer thread runs their destructors before they are collected —
meaning finalized objects survive one extra GC cycle.

IDisposable and using:


For deterministic resource cleanup without waiting for GC, classes implement the
IDisposable interface with a Dispose() method. The using statement automatically calls
Dispose() when the block exits — even if an exception occurs — ensuring prompt resource

release.

Powered by Claude Exporter 303/382


Advantages and Disadvantages:
GC eliminates memory leaks, dangling pointers, and manual memory management
overhead — greatly improving developer productivity. However, it introduces non-
deterministic collection timing, "Stop the World" pauses, and is unsuitable for hard real-time
systems.

Conclusion:
The .NET Garbage Collector is a sophisticated, efficient, and largely transparent memory
management system. Its generational model ensures that the most common case — short-
lived objects — is handled cheaply and frequently, while long-lived objects are managed with
less overhead. Through IDisposable and the using statement, developers retain deterministic
control over critical resources when needed.

⭐ Probable Exam Questions


1. What is garbage collection? What are the various stages? Why is it important in memory
management? (M-23 Q7a) ← directly asked

2. Discuss base class libraries. How is debugging implemented in .NET? (J-21 Q6b) ← GC is part
of this

3. Explain the generational model of garbage collection in .NET.

4. What is IDisposable? How does the using statement help with resource management?

5. What are the advantages and disadvantages of garbage collection?

6. Differentiate between finalization and disposal in .NET.

Unit 3 is flying! 🔥
Remaining:

Topic 8 — Files and Streams ⭐


Topic 9 — Delegates and Events

Topic 10 — Attributes

Topic 11 — I/O in C#

Ready for Topic 8: Files and Streams? 🚀


6/14/2026, 9:23:10 AM

Powered by Claude Exporter 304/382


yes

6/14/2026, 9:53:31 AM

📌 Topic 8: Files and Streams


EXAM DEFINITION
Files are named storage locations on disk used to persistently store data beyond program
execution. Streams are sequences of bytes that provide a channel for reading and writing
data — either from files, memory, network, or other sources. In C#, file and stream
operations are handled by classes in the [Link] namespace. A stream abstracts the data
source — whether file, network, or memory — behind a uniform read/write interface.

FILE vs STREAM — Key Difference


File Stream

What it is Physical storage on disk Abstract channel of bytes

Location Hard disk / SSD File, memory, network, pipe

Persistence Permanent Temporary (while open)

Access Via stream Directly through stream methods

Analogy Water tank (storage) Water pipe (flow channel)

Simple way to remember:

File = WHERE data is stored

Stream = HOW you read/write that data

[Link] NAMESPACE — Class Overview

Powered by Claude Exporter 305/382


[Link]
├── File ← Static methods for file operations
├── FileInfo ← Instance-based file operations
├── Directory ← Static methods for directory operations
├── DirectoryInfo ← Instance-based directory operations
├── Path ← Path string manipulation utilities

├── Stream (abstract) ← Base class for all streams
│ ├── FileStream ← Read/write raw bytes to/from file
│ ├── MemoryStream ← Read/write bytes in memory
│ └── NetworkStream ← Read/write bytes over network

├── TextReader (abstract) ← Base for text reading
│ ├── StreamReader ← Read text from stream/file
│ └── StringReader ← Read text from string

└── TextWriter (abstract) ← Base for text writing
├── StreamWriter ← Write text to stream/file
└── StringWriter ← Write text to string

PART A: FILE CLASS


Static Methods — Quick Operations

using [Link];

// CHECK existence
bool exists = [Link]("[Link]");
[Link](exists); // True or False

// CREATE and WRITE


[Link]("[Link]", "Hello World!");
// Creates file if not exists, overwrites if exists

// APPEND to file

Powered by Claude Exporter 306/382


[Link]("[Link]", "\nNew line added");

// WRITE multiple lines


string[] lines = {"Line 1", "Line 2", "Line 3"};
[Link]("[Link]", lines);

// READ entire file


string content = [Link]("[Link]");
[Link](content);

// READ all lines into array


string[] allLines = [Link]("[Link]");
foreach (string line in allLines)
[Link](line);

// COPY file
[Link]("[Link]", "[Link]");
[Link]("[Link]", "[Link]", true); // true = overwrite

// MOVE file
[Link]("[Link]", "newlocation/[Link]");

// DELETE file
[Link]("[Link]");

// GET file info


DateTime created = [Link]("[Link]");
DateTime modified = [Link]("[Link]");

PART B: FileInfo CLASS


Instance-based — better when performing multiple operations on same file:

FileInfo fi = new FileInfo("[Link]");

[Link]([Link]); // [Link]

Powered by Claude Exporter 307/382


[Link]([Link]); // C:\Projects\[Link]
[Link]([Link]); // .txt
[Link]([Link]); // file size in bytes
[Link]([Link]); // True/False
[Link]([Link]); // when created
[Link]([Link]); // when last modified
[Link]([Link]); // parent directory

[Link]("[Link]");
[Link]("[Link]");
[Link]();

PART C: DIRECTORY CLASS

// Create directory
[Link]("MyFolder");

// Check existence
bool exists = [Link]("MyFolder");

// Get all files in directory


string[] files = [Link]("MyFolder");
string[] txtFiles = [Link]("MyFolder", "*.txt");

// Get subdirectories
string[] dirs = [Link]("MyFolder");

// Delete directory
[Link]("MyFolder");
[Link]("MyFolder", true); // true = delete recursively

// Move directory
[Link]("OldFolder", "NewFolder");

Powered by Claude Exporter 308/382


// Get current directory
string current = [Link]();

PART D: StreamWriter — Writing Text to File

// Method 1 — using statement (recommended — auto closes!)


using (StreamWriter sw = new StreamWriter("[Link]")) {
[Link]("Hello World");
[Link]("Second line");
[Link]("No newline at end");
} // ← automatically closed here

// Method 2 — Append mode


using (StreamWriter sw = new StreamWriter("[Link]", true)) {
// true = append, false = overwrite (default)
[Link]("Appended line");
}

// Method 3 — manual close


StreamWriter sw2 = new StreamWriter("[Link]");
[Link]("Writing data");
[Link](); // flush buffer to file
[Link](); // must close manually!

PART E: StreamReader — Reading Text from File

// Read line by line


using (StreamReader sr = new StreamReader("[Link]")) {
string line;
while ((line = [Link]()) != null) {
[Link](line);
}
}

Powered by Claude Exporter 309/382


// Read entire file at once
using (StreamReader sr = new StreamReader("[Link]")) {
string content = [Link]();
[Link](content);
}

// Read single line


using (StreamReader sr = new StreamReader("[Link]")) {
string firstLine = [Link]();
[Link](firstLine);
}

// Check end of file


using (StreamReader sr = new StreamReader("[Link]")) {
while (![Link]) {
[Link]([Link]());
}
}

PART F: FileStream — Binary Read/Write


For raw byte operations — images, audio, binary data:

// WRITING bytes
using (FileStream fs = new FileStream("[Link]",
[Link], [Link])) {
byte[] data = {72, 101, 108, 108, 111}; // "Hello" in ASCII
[Link](data, 0, [Link]);
}

// READING bytes
using (FileStream fs = new FileStream("[Link]",
[Link], [Link])) {
byte[] buffer = new byte[100];
int bytesRead = [Link](buffer, 0, [Link]);
string content = [Link](buffer, 0,

Powered by Claude Exporter 310/382


bytesRead);
[Link](content); // Output: Hello
}

FileMode Options
FileMode Behavior

Create Creates new file, overwrites if exists

CreateNew Creates new file, error if exists

Open Opens existing file, error if not exists

OpenOrCreate Opens if exists, creates if not

Append Opens for appending, creates if not exists

Truncate Opens existing, clears content

FileAccess Options

FileAccess Behavior

Read Read only

Write Write only

ReadWrite Both read and write

PART G: BinaryWriter and BinaryReader


For writing/reading primitive types in binary format:

// Writing binary data


using (BinaryWriter bw = new BinaryWriter(
new FileStream("[Link]", [Link]))) {
[Link](42); // int
[Link](3.14); // double
[Link]("Hello"); // string

Powered by Claude Exporter 311/382


[Link](true); // bool
}

// Reading binary data — must read in SAME ORDER!


using (BinaryReader br = new BinaryReader(
new FileStream("[Link]", [Link]))) {
int n = br.ReadInt32();
double d = [Link]();
string s = [Link]();
bool b = [Link]();

[Link]($"{n}, {d}, {s}, {b}");


// Output: 42, 3.14, Hello, True
}

COMPLETE PRACTICAL EXAMPLE

using System;
using [Link];

class FileDemo {
static void Main() {

string path = "[Link]";

// WRITE student data


using (StreamWriter sw = new StreamWriter(path)) {
[Link]("Name,Age,Marks");
[Link]("Tannu,21,88.5");
[Link]("Riya,20,92.0");
[Link]("Aman,22,78.3");
}
[Link]("Data written successfully!");

// READ student data

Powered by Claude Exporter 312/382


[Link]("\nReading student data:");
using (StreamReader sr = new StreamReader(path)) {
string line;
while ((line = [Link]()) != null) {
string[] parts = [Link](',');
if (parts[0] != "Name") { // skip header
[Link]($"Name: {parts[0]}, " +
$"Age: {parts[1]}, " +
$"Marks: {parts[2]}");
}
}
}

// CHECK file info


FileInfo fi = new FileInfo(path);
[Link]($"\nFile size: {[Link]} bytes");
[Link]($"Created: {[Link]}");
}
}

Output:

Data written successfully!

Reading student data:


Name: Tannu, Age: 21, Marks: 88.5
Name: Riya, Age: 20, Marks: 92.0
Name: Aman, Age: 22, Marks: 78.3

File size: 67 bytes


Created: 14/06/2026 10:30:00

PATH CLASS — Utility Methods

Powered by Claude Exporter 313/382


string fullPath = @"C:\Projects\MyApp\[Link]";

[Link]([Link](fullPath)); // [Link]
[Link]([Link](fullPath)); //
data
[Link]([Link](fullPath)); // .txt
[Link]([Link](fullPath)); //
C:\Projects\MyApp
[Link]([Link]("[Link]")); // absolute path

// Combine paths safely


string newPath = [Link]("C:\\Projects", "MyApp", "[Link]");
[Link](newPath); // C:\Projects\MyApp\[Link]

// Temp path
[Link]([Link]()); // system temp directory
[Link]([Link]()); // unique temp file

EXCEPTION HANDLING WITH FILES


Always handle file exceptions:

try {
using (StreamReader sr = new StreamReader("[Link]")) {
[Link]([Link]());
}
}
catch (FileNotFoundException ex) {
[Link]("File not found: " + [Link]);
}
catch (UnauthorizedAccessException ex) {
[Link]("No permission: " + [Link]);
}
catch (IOException ex) {
[Link]("IO Error: " + [Link]);

Powered by Claude Exporter 314/382


}
finally {
[Link]("File operation attempted");
}

FEATURES / CHARACTERISTICS
Abstraction — Stream hides whether source is file, memory, or network

Buffering — StreamReader/Writer buffer data for efficiency

using Statement — Ensures streams always closed — even on exception

Encoding Support — StreamReader/Writer handle character encoding (UTF-8, ASCII etc.)

Random Access — FileStream supports Seek() for random file access

Binary + Text — Both text (StreamReader/Writer) and binary (FileStream,


BinaryReader/Writer) supported

ADVANTAGES
Persistence — Data survives program termination

Large Data — Handle data too large for memory

Sharing — Files shared between applications

Flexibility — Text, binary, random access all supported

using Safety — Guaranteed resource release

DISADVANTAGES
Slower than Memory — Disk I/O much slower than RAM

Exception-Prone — File missing, locked, permission denied

Manual Structure — Developer responsible for data format

Encoding Issues — Wrong encoding causes garbled data

DIAGRAM GUIDANCE
Draw: Stream Architecture Diagram

Powered by Claude Exporter 315/382


Left side: Application Code

Center: Stream (pipe)

Top pipe: StreamWriter / BinaryWriter (writing)

Bottom pipe: StreamReader / BinaryReader (reading)

Right side: Data Source (File on disk / Memory / Network)

Arrows showing data flowing through pipes in both directions

Draw: [Link] Class Hierarchy

Root: [Link]

Branch 1: File classes — File, FileInfo

Branch 2: Directory classes — Directory, DirectoryInfo

Branch 3: Stream classes — Stream → FileStream, MemoryStream

Branch 4: Text classes — StreamReader, StreamWriter

Branch 5: Binary classes — BinaryReader, BinaryWriter

LONG ANSWER WRITING VERSION (14-Mark Ready)


Introduction:
Files and Streams are fundamental I/O mechanisms in C#. A file is a named storage location
on disk for persistent data storage. A stream is an abstract channel of bytes through which
data flows between a program and a data source. All file and stream operations in C# are
provided by the [Link] namespace.

The Stream Concept:


A stream abstracts the underlying data source — whether a file on disk, data in memory, or
bytes from a network connection — behind a uniform interface. This allows the same
reading/writing code to work with different sources. The Stream class is the abstract base;
FileStream , MemoryStream , and NetworkStream are concrete implementations.

File Class:
The static File class provides quick one-line operations — WriteAllText() ,
ReadAllText() , WriteAllLines() , ReadAllLines() , Copy() , Move() , Delete() , and

Exists() . The FileInfo class provides the same operations as instance methods,
preferred when performing multiple operations on the same file.

Powered by Claude Exporter 316/382


StreamWriter and StreamReader:
StreamWriter writes text data to a stream or file — line by line using WriteLine() or

without newline using Write() . It supports append mode via a constructor overload.
StreamReader reads text data — line by line using ReadLine() or entirely using

ReadToEnd() . Both should be used with the using statement to ensure they are always
closed properly.

FileStream:
FileStream provides raw byte-level access to files. It is used for binary data like images,

audio, or serialized objects. It supports FileMode (Create, Open, Append) and FileAccess
(Read, Write, ReadWrite) parameters. BinaryWriter and BinaryReader wrap FileStream to
conveniently write and read primitive types in binary format.

Path Class:
The Path class provides utility methods for manipulating file path strings —
GetFileName() , GetExtension() , GetDirectoryName() , Combine() , and GetTempPath()

— without actually accessing the file system.

Exception Handling:
File operations should always be wrapped in try-catch blocks to handle
FileNotFoundException , UnauthorizedAccessException , and IOException . The finally
block or using statement ensures streams are closed even when exceptions occur.

Conclusion:
The [Link] namespace provides a rich, well-structured set of classes for all file and
stream operations in C#. From simple one-line file reads using the File class to complex
binary serialization using BinaryWriter/Reader , C# offers the right tool for every I/O
scenario. The using statement ensures safe resource management by guaranteeing stream
closure regardless of exceptions.

⭐ Probable Exam Questions


1. Explain files and streams with example. (M-23 Q6a) ← directly asked

2. Differentiate between file and stream. (M-24 compulsory) ← directly asked

3. Write a C# program to read and write data to a file using StreamReader and StreamWriter.

4. Explain FileStream with FileMode and FileAccess options.

5. What is the role of the using statement in file handling?

Powered by Claude Exporter 317/382


6. Explain the [Link] namespace and its important classes.

Looking great Tannu! 💪


Remaining Unit 3 topics:

Topic 9 — Delegates and Events (revision + expand)

Topic 10 — Attributes

Topic 11 — I/O in C# and Windows Applications

Ready for Topic 9: Delegates and Events? 🚀


6/14/2026, 9:54:35 AM

Powered by Claude Exporter 318/382


yes sir :)

6/14/2026, 10:25:56 AM

📌 Topic 9: Delegates and Their Usefulness + Events


EXAM DEFINITION
A Delegate is a type-safe object in C# that holds a reference to a method — similar to a
function pointer in C/C++ but safer and object-oriented. It allows methods to be passed as
parameters, stored in variables, and invoked dynamically at runtime. An Event is a
mechanism built on delegates that allows a class (publisher) to notify other classes
(subscribers) when something significant happens — implementing the Publisher-
Subscriber design pattern.

CORE CONCEPT — Why Delegates?


Without delegates — you're stuck calling methods directly:

void ProcessData(int[] data) {


[Link](data); // hardcoded — cannot change behavior!
}

With delegates — behavior can be passed as parameter:

void ProcessData(int[] data, Action<int[]> operation) {


operation(data); // flexible — any method can be passed!
}

ProcessData(nums, [Link]); // sort behavior


ProcessData(nums, [Link]); // reverse behavior

PART A: DELEGATES

Powered by Claude Exporter 319/382


Step 1 — Declare Delegate Type

// Syntax: delegate returnType DelegateName(parameters);


delegate int MathOperation(int a, int b);
delegate void PrintMessage(string message);
delegate bool Validator(string input);

Step 2 — Create Methods Matching Signature

int Add(int a, int b) { return a + b; }


int Subtract(int a, int b) { return a - b; }
int Multiply(int a, int b) { return a * b; }

Step 3 — Create Delegate Instance

MathOperation op = new MathOperation(Add);


// OR shorthand:
MathOperation op = Add;

Step 4 — Invoke Delegate

int result = op(10, 5); // calls Add(10, 5)


[Link](result); // Output: 15

op = Subtract;
result = op(10, 5); // calls Subtract(10, 5)
[Link](result); // Output: 5

COMPLETE DELEGATE EXAMPLE

using System;

// Delegate declaration

Powered by Claude Exporter 320/382


delegate double Calculator(double a, double b);

class Program {

// Methods matching delegate signature


static double Add(double a, double b) { return a + b; }
static double Subtract(double a, double b) { return a - b; }
static double Multiply(double a, double b) { return a * b; }
static double Divide(double a, double b) {
if (b == 0) throw new DivideByZeroException();
return a / b;
}

// Method that TAKES delegate as parameter


static void PerformOperation(double x, double y,
Calculator operation, string opName)
{
double result = operation(x, y);
[Link]($"{opName}({x}, {y}) = {result}");
}

static void Main() {


// Pass different methods via delegate
PerformOperation(10, 5, Add, "Add");
PerformOperation(10, 5, Subtract, "Subtract");
PerformOperation(10, 5, Multiply, "Multiply");
PerformOperation(10, 5, Divide, "Divide");
}
}

Output:

Add(10, 5) = 15
Subtract(10, 5) = 5

Powered by Claude Exporter 321/382


Multiply(10, 5) = 50
Divide(10, 5) = 2

MULTICAST DELEGATE ⭐
One delegate pointing to multiple methods — all called in sequence:

delegate void Notification(string message);

static void SendEmail(string msg) {


[Link]("Email: " + msg);
}
static void SendSMS(string msg) {
[Link]("SMS: " + msg);
}
static void LogMessage(string msg) {
[Link]("Log: " + msg);
}

static void Main() {


// Build multicast delegate using +=
Notification notify = SendEmail;
notify += SendSMS;
notify += LogMessage;

// Invoke — calls ALL three methods!


notify("Server is down!");

// Remove a method using -=


notify -= SendSMS;
notify("Server restored!"); // only Email + Log now
}

Output:

Powered by Claude Exporter 322/382


Email: Server is down!
SMS: Server is down!
Log: Server is down!
Email: Server restored!
Log: Server restored!

ANONYMOUS METHODS
Define method inline without a name:

delegate int Square(int n);

Square sq = delegate(int n) {
return n * n;
};

[Link](sq(5)); // Output: 25
[Link](sq(7)); // Output: 49

LAMBDA EXPRESSIONS — Modern Way ⭐


Shorter syntax for anonymous methods:

delegate int Square(int n);

// Lambda expression
Square sq = n => n * n;

[Link](sq(5)); // Output: 25

// Multi-line lambda
delegate int MaxOf(int a, int b);
MaxOf max = (a, b) => {
if (a > b) return a;
return b;

Powered by Claude Exporter 323/382


};
[Link](max(10, 20)); // Output: 20

BUILT-IN DELEGATE TYPES ⭐ Important!


.NET provides ready-made delegate types — no need to declare your own:

Action — returns void

Action<string> print = msg => [Link](msg);


print("Hello Action!"); // Output: Hello Action!

Action<int, int> printSum = (a, b) =>


[Link]("Sum: " + (a + b));
printSum(3, 4); // Output: Sum: 7

Action noParams = () => [Link]("No parameters!");


noParams();

Func — returns a value

Func<int, int> square = n => n * n;


[Link](square(5)); // Output: 25

Func<int, int, int> add = (a, b) => a + b;


[Link](add(3, 4)); // Output: 7

// Last type parameter is always return type


Func<string, int, string> format =
(name, age) => $"{name} is {age} years old";
[Link](format("Tannu", 21));

Predicate — returns bool

Powered by Claude Exporter 324/382


Predicate<int> isEven = n => n % 2 == 0;
[Link](isEven(4)); // True
[Link](isEven(7)); // False

Predicate<string> isLong = s => [Link] > 5;


[Link](isLong("Hi")); // False
[Link](isLong("Hello World")); // True

Built-in Delegates Summary


Delegate Signature Returns Example

Action<T> Takes T, returns nothing void Action<string>

Func<T, TResult> Takes T, returns TResult TResult Func<int, bool>

Predicate<T> Takes T, returns bool bool Predicate<int>

USEFULNESS OF DELEGATES ⭐
Examiners ask specifically about usefulness — cover all points:

1. Callback Methods

// Notify when download complete


void Download(string url, Action<string> onComplete) {
// ... download logic ...
onComplete("Download finished: " + url);
}

Download("[Link]", msg => [Link](msg));

2. Event Handling (UI)

[Link] += (sender, e) => [Link]("Button clicked!");

Powered by Claude Exporter 325/382


3. LINQ Operations

List<int> nums = new List<int>{1,2,3,4,5,6,7,8,9,10};

// Func and Predicate used internally by LINQ


var evens = [Link](n => n % 2 == 0); // Predicate
var squares = [Link](n => n * n); // Func
var sum = [Link]((a, b) => a + b); // Func

4. Strategy Pattern

// Sort with different strategies


List<string> names = new List<string>{"Tannu","Riya","Aman"};

[Link]((a, b) => [Link](b)); // alphabetical


[Link]((a, b) => [Link]([Link])); // by length

5. Asynchronous Programming

// Callback when async operation completes


void FetchData(Action<string> callback) {
// simulate async work
string data = "fetched data";
callback(data);
}

PART B: EVENTS
Exam Definition

An Event in C# is a special delegate that implements the Publisher-Subscriber pattern. The


publisher class defines and raises the event. Subscriber classes register handler methods.
When the event is raised, all registered handlers are called automatically.

EVENTS — Step by Step

Powered by Claude Exporter 326/382


Step 1 — Declare delegate for event

delegate void OrderPlacedHandler(string product, int qty);

Step 2 — Declare event using delegate

class OrderSystem {
// event keyword — restricts direct invocation from outside
public event OrderPlacedHandler OnOrderPlaced;
}

Step 3 — Raise event in publisher

class OrderSystem {
public event OrderPlacedHandler OnOrderPlaced;

public void PlaceOrder(string product, int qty) {


[Link]($"Order placed: {product} x{qty}");

// Raise event — notify all subscribers


if (OnOrderPlaced != null)
OnOrderPlaced(product, qty);

// Modern null-safe way:


OnOrderPlaced?.Invoke(product, qty);
}
}

Step 4 — Subscribe in other classes

class EmailService {
public void SendConfirmation(string product, int qty) {
[Link]($"Email: Your order for {product} x{qty}
confirmed!");

Powered by Claude Exporter 327/382


}
}

class InventoryService {
public void UpdateStock(string product, int qty) {
[Link]($"Inventory: Reduced {product} stock by
{qty}");
}
}

class SMSService {
public void SendSMS(string product, int qty) {
[Link]($"SMS: Order for {product} is being
processed!");
}
}

Step 5 — Wire everything in Main

class Program {
static void Main() {
OrderSystem orders = new OrderSystem();
EmailService email = new EmailService();
InventoryService inventory = new InventoryService();
SMSService sms = new SMSService();

// Subscribe — register handlers


[Link] += [Link];
[Link] += [Link];
[Link] += [Link];

// Place order — event fires, all subscribers notified!


[Link]("Laptop", 1);
[Link]();
[Link]("Phone", 2);

Powered by Claude Exporter 328/382


}
}

Output:

Order placed: Laptop x1


Email: Your order for Laptop x1 confirmed!
Inventory: Reduced Laptop stock by 1
SMS: Order for Laptop is being processed!

Order placed: Phone x2


Email: Your order for Phone x2 confirmed!
Inventory: Reduced Phone stock by 2
SMS: Order for Phone is being processed!

EventHandler — Built-in Event Delegate


.NET provides a standard EventHandler delegate for events:

class Button {
// Using built-in EventHandler
public event EventHandler OnClick;

public void Click() {


[Link]("Button clicked!");
OnClick?.Invoke(this, [Link]);
}
}

class Program {
static void HandleClick(object sender, EventArgs e) {
[Link]("Click handled!");
}

static void Main() {


Button btn = new Button();

Powered by Claude Exporter 329/382


[Link] += HandleClick;
[Link] += (s, e) => [Link]("Lambda
handler!");

[Link]();
}
}

Output:

Button clicked!
Click handled!
Lambda handler!

DELEGATE vs EVENT — Key Difference


Delegate Event

What it is Type holding method reference Notification mechanism

Invocation Can be invoked from anywhere Only from declaring class

Assignment Can use = (replace all) Only += and -= allowed outside class

Purpose Callbacks, passing methods Publisher-subscriber notifications

Keyword delegate event

Based on Itself Delegate

Example LINQ, callbacks [Link], custom notifications

PUBLISHER-SUBSCRIBER PATTERN DIAGRAM

┌─────────────────────┐ ┌──────────────────────┐
│ PUBLISHER │ │ SUBSCRIBER 1 │
│ (OrderSystem) │─────→ │ (EmailService) │
│ │ └──────────────────────┘
│ event OnOrderPlaced │ ┌──────────────────────┐

Powered by Claude Exporter 330/382


│ PlaceOrder() raises │─────→ │ SUBSCRIBER 2 │
│ the event │ │ (InventoryService) │
│ │ └──────────────────────┘
└─────────────────────┘ ┌──────────────────────┐
─────→ │ SUBSCRIBER 3 │
│ (SMSService) │
└──────────────────────┘

FEATURES OF DELEGATES
Type-Safe — Compiler ensures method signature matches delegate

Object-Oriented — Delegates are objects — can be stored, passed, returned

Multicast — One delegate can invoke multiple methods

Foundation of Events — Events built entirely on delegates

LINQ Integration — Func, Action, Predicate power all LINQ operations

ADVANTAGES OF DELEGATES
Flexibility — Behavior can be passed as parameter

Decoupling — Caller doesn't need to know which method runs

Reusability — Same code works with different methods

Async Support — Foundation of async callbacks

Clean Event Model — Events provide structured notification system

DISADVANTAGES
Complexity — Beginners find delegate syntax confusing

Debugging — Hard to trace which methods a multicast delegate calls

Memory Leaks — Forgetting to unsubscribe events can prevent GC

DIAGRAM GUIDANCE
Draw: Delegate Invocation Diagram

Powered by Claude Exporter 331/382


Box: Delegate Object — contains method reference

Arrow from Caller → Delegate → Arrow to Target Method

For multicast: one Delegate box → multiple Target Method boxes

Draw: Event Publisher-Subscriber

Already shown above — use that diagram

Key labels: Publisher raises event, Delegate carries notification, Subscribers handle it

LONG ANSWER WRITING VERSION (14-Mark Ready)


Introduction:
Delegates and Events are powerful features of C# that enable flexible, decoupled, and
extensible programming. A delegate is a type-safe object holding a reference to one or more
methods, allowing methods to be treated as first-class values — passed as parameters,
stored in variables, and invoked dynamically. An event is built on delegates and implements
the Publisher-Subscriber pattern — allowing objects to notify other objects when significant
actions occur.

Delegates:
A delegate is declared using the delegate keyword with a specific return type and
parameter list. Methods matching this signature can be assigned to delegate instances.
Delegates can be invoked like regular methods. A key feature is multicast delegates —
using += to add multiple methods so one invocation calls all registered methods in
sequence. Built-in delegate types include Action (void return), Func (typed return), and
Predicate (bool return) — covering most use cases without custom declarations.

Lambda Expressions:
Modern C# uses lambda expressions as concise inline method definitions assigned to
delegates: Func<int,int> square = n => n * n . Lambda expressions combined with built-
in delegates power LINQ operations — Where() , Select() , OrderBy() all accept Func and
Predicate delegates.

Usefulness of Delegates:
Delegates are useful in multiple scenarios. As callback mechanisms — passing a method to
be called when an operation completes. In LINQ — lambda expressions as delegates power
all query operations. In the Strategy pattern — passing different algorithm

Powered by Claude Exporter 332/382


implementations. In asynchronous programming — callbacks when async operations
finish. In event handling — the foundation of all UI and business event systems.

Events:
An event is declared using the event keyword with a delegate type. Only the declaring class
can raise (invoke) the event — external classes can only subscribe ( += ) or unsubscribe ( -= ).
This restriction provides encapsulation. When the publisher raises the event, all subscribed
handler methods are automatically called. The built-in EventHandler delegate provides a
standard signature for events.

Publisher-Subscriber Pattern:
Events implement the Publisher-Subscriber pattern — the publisher class defines and raises
events without knowing who the subscribers are. Subscribers register their handler methods
via += . This decouples publisher and subscriber — adding new subscribers requires no
changes to the publisher.

Delegate vs Event:
The key difference is invocation control. A delegate can be invoked from anywhere. An event
can only be raised from within the declaring class — providing encapsulation. Events also
restrict assignment to += and -= only — preventing accidental replacement of all
subscribers.

Conclusion:
Delegates and events form the backbone of C#'s flexible, decoupled programming model.
Delegates enable methods to be first-class values — passed, stored, and invoked
dynamically. Events build on delegates to provide a structured, encapsulated notification
system. Together they power LINQ, asynchronous programming, UI event handling, and
enterprise notification systems — making them among the most important and widely used
features of C#.

⭐ Probable Exam Questions


1. Write short notes on Delegates. (J-21 Q7a) ← directly asked

2. Define the term delegates. How is it distinguished from events? Enlist usefulness. (M-24 Q7b)
← directly asked

3. Explain delegates and events with suitable example.

4. What are multicast delegates? Explain with example.

5. Explain Action, Func, and Predicate delegates in C#.

Powered by Claude Exporter 333/382


6. What is the Publisher-Subscriber pattern? How is it implemented using events?

Two topics left! 🔥


Remaining:

Topic 10 — Attributes

Topic 11 — I/O in C# and Windows Applications

Ready for Topic 10: Attributes? 🚀


6/14/2026, 10:27:07 AM

Powered by Claude Exporter 334/382


yes :)

6/14/2026, 10:43:18 AM

📌 Topic 10: Attributes


EXAM DEFINITION
Attributes in C# are special declarative tags that add metadata (additional information) to
program elements such as classes, methods, properties, fields, and assemblies. They are
placed in square brackets [] above the element they describe. Attributes do not change
the logic of the code directly — instead they provide instructions to the compiler, CLR, or
other tools about how to treat the decorated element. Attributes are defined as classes
inheriting from [Link] .

CORE CONCEPT
Think of attributes like sticky notes on your code:

The code itself does its job

The sticky note gives extra instructions to whoever reads it

Compiler, CLR, Visual Studio, testing frameworks — all read these notes

Real-world analogy:

A file folder in an office

[Urgent] tag on it → tells everyone to handle it first

The folder's contents don't change — just how it's treated does

SYNTAX

[AttributeName] // no parameters
[AttributeName(value)] // with positional parameter

Powered by Claude Exporter 335/382


[AttributeName(Property = value)] // with named parameter

// On a class
[Serializable]
class Student { }

// On a method
[Obsolete("Use NewMethod() instead")]
void OldMethod() { }

// Multiple attributes
[Serializable]
[Obsolete("Old class")]
class LegacyClass { }

// Multiple on same line


[Serializable, Obsolete("Old")]
class LegacyClass { }

BUILT-IN ATTRIBUTES IN C#
1. [Obsolete] — Mark as outdated

class MathHelper {

[Obsolete("Use AddNumbers() instead", false)]


public int Add(int a, int b) {
return a + b;
}

// false = warning only, true = compile error


[Obsolete("This method is removed!", true)]
public int OldAdd(int a, int b) {
return a + b;
}

Powered by Claude Exporter 336/382


public int AddNumbers(int a, int b) {
return a + b;
}
}

// Usage:
MathHelper m = new MathHelper();
[Link](1, 2); // ⚠️ Warning: 'Add' is obsolete: Use
AddNumbers()
[Link](1, 2); // ❌ Error: This method is removed!
[Link](1, 2); // ✅ No warning

2. [Serializable] — Mark for serialization

[Serializable]
class Student {
public string Name;
public int Age;

[NonSerialized] // exclude this field from serialization


public string Password;
}

Marks class so its objects can be converted to byte stream (saved to file/sent over
network)

[NonSerialized] excludes specific fields

3. [DllImport] — Call native DLL functions

using [Link];

class NativeInterop {
[DllImport("[Link]")]

Powered by Claude Exporter 337/382


public static extern int MessageBox(int h, string msg,
string title, int type);
}

// Call Win32 MessageBox from C#!


[Link](0, "Hello!", "My App", 0);

4. [Conditional] — Conditional compilation

using [Link];

class Logger {
[Conditional("DEBUG")]
public static void Log(string message) {
[Link]("DEBUG: " + message);
}
}

// Log() only called in DEBUG builds


// In RELEASE build — calls to Log() completely removed by compiler!
[Link]("This only shows in debug mode");

5. [AttributeUsage] — Controls how custom attributes are used

[AttributeUsage(
[Link] | [Link],
AllowMultiple = false,
Inherited = true
)]
public class MyAttribute : Attribute { }

Parameters:

AttributeTargets — where attribute can be applied

Powered by Claude Exporter 338/382


AllowMultiple — can apply same attribute multiple times?

Inherited — does derived class inherit this attribute?

6. [WebMethod] — [Link] Web Service method

[WebMethod]
public string HelloWorld() {
return "Hello from Web Service!";
}

7. Assembly-Level Attributes

// [Link]
[assembly: AssemblyTitle("My Application")]
[assembly: AssemblyVersion("[Link]")]
[assembly: AssemblyCompany("MyCompany")]
[assembly: AssemblyCopyright("Copyright 2026")]
[assembly: CLSCompliant(true)]

ATTRIBUTE TARGETS
AttributeTargets Applied To

Assembly Entire assembly

Class Class declaration

Method Method declaration

Property Property declaration

Field Field declaration

Parameter Method parameter

ReturnValue Return value

Interface Interface declaration

Powered by Claude Exporter 339/382


AttributeTargets Applied To

All Any element

CUSTOM ATTRIBUTES ⭐ Important!


Create your own attribute by inheriting from [Link] :

// Step 1 — Define custom attribute


[AttributeUsage([Link] | [Link])]
public class AuthorAttribute : Attribute {
// Properties
public string Name { get; set; }
public string Version { get; set; }
public string Date { get; set; }

// Constructor
public AuthorAttribute(string name) {
Name = name;
Version = "1.0";
Date = [Link]("dd/MM/yyyy");
}
}

// Step 2 — Apply custom attribute


[Author("Tannu", Version = "2.0", Date = "14/06/2026")]
class StudentManager {

[Author("Riya")]
public void AddStudent() {
[Link]("Student added");
}

[Author("Aman", Version = "1.5")]


public void DeleteStudent() {
[Link]("Student deleted");

Powered by Claude Exporter 340/382


}
}

READING ATTRIBUTES AT RUNTIME — REFLECTION


Attributes are read using Reflection:

using [Link];

class Program {
static void Main() {
// Get type info
Type type = typeof(StudentManager);

// Read class-level attribute


AuthorAttribute classAttr = (AuthorAttribute)
[Link](type,
typeof(AuthorAttribute));

if (classAttr != null) {
[Link]($"Class Author: {[Link]}");
[Link]($"Version: {[Link]}");
[Link]($"Date: {[Link]}");
}

// Read method-level attributes


foreach (MethodInfo method in [Link]()) {
AuthorAttribute methodAttr = (AuthorAttribute)
[Link](method,
typeof(AuthorAttribute));

if (methodAttr != null) {
[Link]($"Method: {[Link]}, " +
$"Author: {[Link]}");
}
}

Powered by Claude Exporter 341/382


}
}

Output:

Class Author: Tannu


Version: 2.0
Date: 14/06/2026
Method: AddStudent, Author: Riya
Method: DeleteStudent, Author: Aman

REFLECTION — Brief Overview ⭐


Reflection is the ability of a program to inspect its own metadata at runtime — examine
types, methods, properties, and attributes without knowing them at compile time.

using [Link];

class Program {
static void Main() {
Type type = typeof(Student);

// Get class name


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

// Get all properties


[Link]("\nProperties:");
foreach (PropertyInfo prop in [Link]())
[Link](" " + [Link] + ": " +
[Link]);

// Get all methods


[Link]("\nMethods:");
foreach (MethodInfo method in [Link]())
[Link](" " + [Link]);

Powered by Claude Exporter 342/382


// Create object dynamically
object obj = [Link](type);
}
}

class Student {
public string Name { get; set; }
public int Age { get; set; }
public double Marks { get; set; }

public void Display() { }


public string GetGrade() { return "A"; }
}

Output:

Class: Student

Properties:
Name: String
Age: Int32
Marks: Double

Methods:
Display
GetGrade
ToString
Equals
GetHashCode
GetType

BUILT-IN ATTRIBUTES SUMMARY TABLE


Attribute Applied To Purpose

[Obsolete] Method, Class Mark as outdated

Powered by Claude Exporter 343/382


Attribute Applied To Purpose

[Serializable] Class Enable serialization

[NonSerialized] Field Exclude from serialization

[DllImport] Method Call native DLL

[Conditional] Method Conditional compilation

[AttributeUsage] Attribute class Control attribute usage

[CLSCompliant] Assembly Mark CLS compliance

[WebMethod] Method Expose as web service

[AssemblyVersion] Assembly Set version number

FEATURES / CHARACTERISTICS
Declarative — Add metadata without changing code logic

Extensible — Create custom attributes by inheriting [Link]

Runtime Accessible — Read via Reflection at runtime

Compile-Time — Some attributes affect compiler behavior directly

Hierarchical — Can control inheritance via AttributeUsage

Multiple — Multiple attributes can decorate same element

ADVANTAGES
Self-Documenting — Code carries its own metadata

Framework Integration — Testing frameworks, ORM tools, serializers use attributes

Separation of Concerns — Metadata separate from business logic

No Performance Cost — Attributes only read when needed via Reflection

Extensible — Custom attributes for any purpose

DISADVANTAGES
Reflection Overhead — Reading attributes at runtime via Reflection has cost

Powered by Claude Exporter 344/382


Not Immediately Visible — Effect of attribute not always obvious from code

Magic Behavior — Frameworks doing things based on attributes can be hard to debug

DIAGRAM GUIDANCE
Draw: Attribute Position Diagram

Show code structure with attribute labels:

[Serializable] ← Attribute
class Student { ← Applied to class
[NonSerialized] ← Attribute
string password; ← Applied to field

[Obsolete] ← Attribute
void OldMethod() ← Applied to method
}

Draw: Custom Attribute Flow

Box 1: Define AuthorAttribute : Attribute

Box 2: Apply [Author("Tannu")] on class/method

Box 3: Read using Reflection at runtime

Arrow through all three boxes labeled: "Attribute Lifecycle"

LONG ANSWER WRITING VERSION (14-Mark Ready)


Introduction:
Attributes in C# are declarative tags that attach metadata to program elements — classes,
methods, fields, properties, and assemblies. Placed in square brackets [] above the target
element, attributes provide instructions to the compiler, CLR, or tools like testing frameworks
and ORM libraries. They are instances of classes inheriting from [Link] and can
be read at runtime using Reflection.

Built-in Attributes:
C# provides several important built-in attributes. [Obsolete] marks methods or classes as

Powered by Claude Exporter 345/382


outdated — generating compiler warnings or errors when used. [Serializable] marks a
class for serialization — allowing its objects to be converted to byte streams for storage or
network transmission. [NonSerialized] excludes specific fields from serialization.
[DllImport] enables calling functions from native Windows DLLs — essential for

interoperability. [Conditional] makes method calls conditional on compilation symbols —


useful for debug-only logging.

Assembly-Level Attributes:
Attributes can target entire assemblies using the [assembly: ...] syntax. These include
AssemblyVersion , AssemblyTitle , AssemblyCompany , and CLSCompliant — all stored in
[Link] and embedded in the assembly manifest.

Custom Attributes:
Developers create custom attributes by inheriting from [Link] . The
[AttributeUsage] attribute controls where the custom attribute can be applied (class,

method, property etc.), whether it can be applied multiple times ( AllowMultiple ), and
whether derived classes inherit it ( Inherited ). Custom attributes can have constructors for
required parameters and properties for optional parameters.

Reflection and Attributes:


Attributes are read at runtime using the Reflection API — specifically
[Link]() and [Link]() . Reflection allows
programs to inspect their own structure — discovering types, methods, properties, and their
associated attributes dynamically. This powers frameworks like NUnit (test attributes), Entity
Framework (mapping attributes), and [Link] (routing attributes).

Attribute Targets:
The AttributeTargets enum specifies valid targets — Assembly , Class , Method ,
Property , Field , Parameter , ReturnValue , and Interface . Multiple targets can be
combined using the | operator.

Conclusion:
Attributes are a powerful metadata mechanism in C# that enable declarative programming
— expressing intent and configuration directly in code without changing logic. From marking
obsolete code to enabling serialization, from DLL interop to custom frameworks — attributes
provide a clean, extensible way to attach instructions to code elements. Combined with
Reflection, they enable runtime inspection and dynamic behavior that powers modern C#
frameworks and libraries.

Powered by Claude Exporter 346/382


⭐ Probable Exam Questions
1. What are attributes in C#? Explain built-in attributes with examples.

2. How do you create a custom attribute in C#? Explain with example.

3. What is Reflection in C#? How is it used to read attributes?

4. Explain [Obsolete], [Serializable], and [DllImport] attributes.

5. What is [AttributeUsage]? Explain its parameters.

6. Write a short note on attributes in C#.

One topic left! 🎉


Final topic:

Topic 11 — I/O in C# and Windows Applications

Ready for the last topic of Unit 3? 🚀


6/14/2026, 10:44:13 AM

Powered by Claude Exporter 347/382


yes

6/14/2026, 10:53:10 AM

📌 Topic 11: I/O in C# and Windows Applications


EXAM DEFINITION
I/O (Input/Output) in C# refers to the mechanisms for reading data from input sources and
writing data to output destinations. C# provides Console I/O for text-based applications and
Windows Forms for GUI-based applications. Console I/O uses the [Link] class for
reading from keyboard and writing to screen. Windows Forms provides visual controls like
TextBox, Button, Label, and ListBox for rich graphical user interaction.

PART A: CONSOLE I/O


Console Output Methods

// Write — no newline at end


[Link]("Hello ");
[Link]("World");
// Output: Hello World (on same line)

// WriteLine — with newline


[Link]("Hello World");
[Link]("Second line");
// Output:
// Hello World
// Second line

// Formatted output
[Link]("Name: {0}, Age: {1}", "Tannu", 21);
// Output: Name: Tannu, Age: 21

Powered by Claude Exporter 348/382


// String interpolation
string name = "Tannu";
int age = 21;
[Link]($"Name: {name}, Age: {age}");

// Format numbers
double price = 1234.5678;
[Link]($"Price: {price:F2}"); // 2 decimal places →
1234.57
[Link]($"Price: {price:C}"); // currency → ₹1,234.57
[Link]($"Price: {price:E}"); // scientific →
1.234568E+003

// Console colors
[Link] = [Link];
[Link]("Success message!");
[Link] = [Link];
[Link]("Error message!");
[Link](); // back to default

// Clear console
[Link]();

// Console title and size


[Link] = "My Application";
[Link] = 80;
[Link] = 30;

Console Input Methods

// Read single character (returns int — ASCII value)


int ch = [Link]();
[Link]((char)ch);

Powered by Claude Exporter 349/382


// Read entire line as string
string name = [Link]();
[Link]("Hello " + name);

// Read key (no enter needed)


ConsoleKeyInfo key = [Link]();
[Link]("\nYou pressed: " + [Link]);

// Reading different data types


[Link]("Enter age: ");
int age = [Link]([Link]());

[Link]("Enter salary: ");


double salary = [Link]([Link]());

[Link]("Enter name: ");


string personName = [Link]();

// Safe reading with TryParse


[Link]("Enter a number: ");
string input = [Link]();
int number;
if ([Link](input, out number))
[Link]("Valid number: " + number);
else
[Link]("Invalid input!");

Console I/O Complete Example

using System;

class StudentEntry {
static void Main() {
[Link] = "Student Entry System";
[Link] = [Link];

Powered by Claude Exporter 350/382


[Link]("===== Student Entry System =====");
[Link]();

[Link]("Enter student name: ");


string name = [Link]();

[Link]("Enter age: ");


int age = [Link]([Link]());

[Link]("Enter marks: ");


double marks = [Link]([Link]());

// Calculate grade
string grade;
if (marks >= 90) grade = "A";
else if (marks >= 75) grade = "B";
else if (marks >= 60) grade = "C";
else grade = "F";

[Link]("\n===== Student Report =====");


[Link]($"Name : {name}");
[Link]($"Age : {age}");
[Link]($"Marks : {marks:F2}");
[Link]($"Grade : {grade}");

[Link]("\nPress any key to exit...");


[Link]();
}
}

Output:

===== Student Entry System =====


Enter student name: Tannu
Enter age: 21
Enter marks: 88.5

Powered by Claude Exporter 351/382


===== Student Report =====
Name : Tannu
Age : 21
Marks : 88.50
Grade : B

Press any key to exit...

PART B: WINDOWS FORMS (GUI I/O)


What are Windows Forms?

Windows Forms (WinForms) is a GUI framework in .NET for building desktop applications
with visual controls — buttons, text boxes, labels, menus, and more. Every form is a class
inheriting from [Link] .

[Link]
├── Form ← Window/Dialog base class
├── Controls
│ ├── Button ← Clickable button
│ ├── TextBox ← Text input field
│ ├── Label ← Display text
│ ├── ListBox ← List of items
│ ├── ComboBox ← Dropdown list
│ ├── CheckBox ← Toggle checkbox
│ ├── RadioButton ← Option selector
│ ├── PictureBox ← Display image
│ ├── Panel ← Container for controls
│ ├── GroupBox ← Named container
│ ├── DataGridView ← Table/grid display
│ └── MenuStrip ← Menu bar
├── Dialogs
│ ├── MessageBox ← Popup message
│ ├── OpenFileDialog ← File open dialog
│ ├── SaveFileDialog ← File save dialog

Powered by Claude Exporter 352/382


│ └── ColorDialog ← Color picker
└── Timers
└── Timer ← Timed events

Creating a Windows Form — Code Approach

using System;
using [Link];
using [Link];

class StudentForm : Form {

// Controls
Label lblName, lblAge, lblResult;
TextBox txtName, txtAge;
Button btnSubmit, btnClear;
ListBox lstStudents;

public StudentForm() {
// ── FORM SETUP ──
[Link] = "Student Management";
[Link] = new Size(500, 400);
[Link] = [Link];
[Link] = [Link];

// ── LABEL: Name ──
lblName = new Label();
[Link] = "Student Name:";
[Link] = new Point(20, 30);
[Link] = new Size(100, 25);

// ── TEXTBOX: Name ──
txtName = new TextBox();
[Link] = new Point(130, 27);
[Link] = new Size(200, 25);

Powered by Claude Exporter 353/382


[Link] = "Enter name";

// ── LABEL: Age ──
lblAge = new Label();
[Link] = "Age:";
[Link] = new Point(20, 70);
[Link] = new Size(100, 25);

// ── TEXTBOX: Age ──
txtAge = new TextBox();
[Link] = new Point(130, 67);
[Link] = new Size(200, 25);
[Link] = "Enter age";

// ── BUTTON: Submit ──
btnSubmit = new Button();
[Link] = "Add Student";
[Link] = new Point(130, 110);
[Link] = new Size(100, 35);
[Link] = [Link];
[Link] = [Link];
[Link] += BtnSubmit_Click; // event handler

// ── BUTTON: Clear ──
btnClear = new Button();
[Link] = "Clear";
[Link] = new Point(240, 110);
[Link] = new Size(90, 35);
[Link] += BtnClear_Click;

// ── LISTBOX: Students ──
lstStudents = new ListBox();
[Link] = new Point(20, 160);
[Link] = new Size(440, 150);

Powered by Claude Exporter 354/382


// ── LABEL: Result ──
lblResult = new Label();
[Link] = new Point(20, 320);
[Link] = new Size(440, 25);
[Link] = [Link];

// ── ADD CONTROLS TO FORM ──


[Link](new Control[] {
lblName, txtName,
lblAge, txtAge,
btnSubmit, btnClear,
lstStudents, lblResult
});
}

// ── EVENT HANDLERS ──
private void BtnSubmit_Click(object sender, EventArgs e) {
if ([Link]([Link])) {
[Link]("Please enter a name!",
"Validation Error",
[Link],
[Link]);
return;
}

string student = $"{[Link]} (Age: {[Link]})";


[Link](student);

[Link] = $"✓ {[Link]} added successfully!";


[Link] = [Link];

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

Powered by Claude Exporter 355/382


private void BtnClear_Click(object sender, EventArgs e) {
[Link]();
[Link]();
[Link]();
[Link] = "List cleared.";
[Link] = [Link];
}
}

class Program {
static void Main() {
[Link]();
[Link](new StudentForm());
}
}

COMMON WINDOWS FORMS CONTROLS


TextBox

TextBox txt = new TextBox();


[Link] = "Default text";
[Link] = true; // read-only
[Link] = '*'; // password field
[Link] = true; // multiple lines
[Link] = [Link];
[Link] = 50; // max characters
string value = [Link]; // get value
[Link](); // clear text

Button

Button btn = new Button();


[Link] = "Click Me";

Powered by Claude Exporter 356/382


[Link] = false; // disabled
[Link] = [Link];
[Link] += (s, e) => [Link]("Clicked!");

ListBox

ListBox lst = new ListBox();


[Link]("Item 1");
[Link]("Item 2");
[Link]("Item 1");
[Link]();
string selected = [Link]();
int index = [Link];
[Link] = [Link];

ComboBox

ComboBox cmb = new ComboBox();


[Link]("Option 1");
[Link]("Option 2");
[Link] = 0;
string selected = [Link]();
[Link] = [Link];

CheckBox and RadioButton

CheckBox chk = new CheckBox();


[Link] = "Remember me";
[Link] = true;
bool isChecked = [Link];
[Link] += (s, e) => [Link]([Link]);

RadioButton rb1 = new RadioButton();


[Link] = "Male";

Powered by Claude Exporter 357/382


[Link] = true;
bool isSelected = [Link];

MessageBox

// Simple message
[Link]("Hello World!");

// With title
[Link]("Are you sure?", "Confirm");

// With buttons
DialogResult result = [Link](
"Delete this record?",
"Confirm Delete",
[Link],
[Link]
);

if (result == [Link])
[Link]("Deleted!");
else
[Link]("Cancelled!");

FORM EVENTS — Common Events

// Form events
[Link] += Form_Load; // when form first loads
[Link] += Form_Closing; // when form about to close
[Link] += Form_Resize; // when form resized

// Control events
[Link] += Button_Click; // button clicked
[Link] += TextBox_TextChanged; // text changed

Powered by Claude Exporter 358/382


[Link] += ListBox_Changed; // selection changed
[Link] += Form_KeyPress; // key pressed

// Event handlers
private void Form_Load(object sender, EventArgs e) {
[Link]("Form loaded!");
}

private void Form_Closing(object sender, FormClosingEventArgs e) {


DialogResult result = [Link]("Exit?", "Confirm",
[Link]);
if (result == [Link])
[Link] = true; // prevent closing!
}

FILE DIALOGS

// Open file dialog


OpenFileDialog openDlg = new OpenFileDialog();
[Link] = "Select a file";
[Link] = "Text Files|*.txt|All Files|*.*";

if ([Link]() == [Link]) {
string filePath = [Link];
string content = [Link](filePath);
[Link] = content;
}

// Save file dialog


SaveFileDialog saveDlg = new SaveFileDialog();
[Link] = "Save file";
[Link] = "Text Files|*.txt";
[Link] = "txt";

if ([Link]() == [Link]) {

Powered by Claude Exporter 359/382


[Link]([Link], [Link]);
[Link]("Saved successfully!");
}

CONTROL PROPERTIES — Common Ones


Property Type Description

Text string Display text

Location Point Position (x, y)

Size Size Width and height

Visible bool Show/hide

Enabled bool Enable/disable

BackColor Color Background color

ForeColor Color Text color

Font Font Text font

TabIndex int Tab order

Name string Control identifier

Tag object Custom data storage

CONSOLE vs WINDOWS FORMS


Console I/O Windows Forms

Interface Text-based Graphical (GUI)

Input [Link]() TextBox, ComboBox

Output [Link]() Label, ListBox

User friendly Less More

Complexity Simple More code needed

Powered by Claude Exporter 360/382


Console I/O Windows Forms

Namespace System [Link]

Use for Tools, servers, scripts Desktop applications

Platform Cross-platform Windows (primarily)

FEATURES / CHARACTERISTICS
Event-Driven — Windows Forms is completely event-driven

Visual Designer — Visual Studio provides drag-and-drop form designer

Rich Controls — Extensive library of ready-made UI controls

Data Binding — Controls can bind directly to data sources

MDI Support — Multiple Document Interface for complex apps

Inheritance — Forms can inherit from other forms

DIAGRAM GUIDANCE
Draw: Windows Forms Architecture

Top box: User (interacts with)

Arrow down to: Windows Form (contains controls)

Inside form box: Button, TextBox, Label, ListBox boxes

Arrow from Button labeled: "Click Event"

Arrow to: Event Handler (your code)

Arrow to: Business Logic / Data

Draw: Console I/O Flow

Box: Keyboard → [Link]() → Program

Box: Program → [Link]() → Screen

LONG ANSWER WRITING VERSION (14-Mark Ready)

Powered by Claude Exporter 361/382


Introduction:
I/O (Input/Output) in C# enables programs to interact with users and external systems. C#
supports two primary I/O models: Console I/O for text-based terminal applications using the
[Link] class, and Windows Forms for rich graphical desktop applications using

the [Link] namespace.

Console I/O:
The Console class provides static methods for all terminal I/O. [Link]() outputs
text without newline; [Link]() adds a newline. [Link]() reads a
complete line of text input; [Link]() reads a single character; [Link]()
reads a keypress without requiring Enter. Console colors can be controlled via
ForegroundColor and BackgroundColor properties. Format specifiers in string
interpolation allow precise numeric formatting — {value:F2} for two decimal places,
{value:C} for currency.

Windows Forms:
Windows Forms is .NET's GUI framework for building desktop applications. Every form is a
class inheriting from [Link] . Controls are instantiated
programmatically or via Visual Studio's drag-and-drop designer. Common controls include
TextBox for text input, Label for display text, Button for actions, ListBox for item lists,
ComboBox for dropdowns, CheckBox and RadioButton for selections. Controls are added to

the form using [Link]() .

Event-Driven Programming:
Windows Forms follows an event-driven model — user interactions (clicks, key presses,
selection changes) raise events. Event handlers — methods matching the event delegate
signature — are registered using += . The [Link] event, [Link]
event, and [Link] event are the most commonly used. Form lifecycle events like Load
and FormClosing allow initialization and cleanup logic.

MessageBox:
[Link]() displays popup dialogs for messages, warnings, confirmations, and
errors. It supports various MessageBoxButtons (OK, YesNo, YesNoCancel) and
MessageBoxIcon options and returns a DialogResult indicating the user's choice.

File Dialogs:
OpenFileDialog and SaveFileDialog provide standard Windows file selection dialogs.

They support file type filters and return the selected file path via FileName property after
ShowDialog() returns [Link] .

Powered by Claude Exporter 362/382


Conclusion:
C# provides comprehensive I/O capabilities through Console I/O for simple text applications
and Windows Forms for rich GUI desktop applications. Console I/O suits server-side,
scripting, and utility applications while Windows Forms provides a complete event-driven GUI
framework for interactive desktop software. Together they cover the full spectrum of user
interaction requirements in C# application development.

⭐ Probable Exam Questions


1. Give an overview of [Link] validation controls. (J-21 Q9b) ← related

2. Explain Windows Forms application development in C#.

3. Write a C# Windows Forms program with TextBox, Button, and Label.

4. Explain Console I/O methods in C# with examples.

5. What are common Windows Forms controls? Explain any five.

6. Explain event handling in Windows Forms applications.

7. What are File Dialogs in Windows Forms? Explain OpenFileDialog.

🎉 UNIT 3 — ALL TOPICS COMPLETE!


# Topic Status

1 Creating DLL Files ✅


2 Assemblies of Multiple Versions ✅
3 GAC Utility and Strong Name ✅
4 Arrays and Strings ✅
5 Boxing and Unboxing ✅
6 Exception Handling ✅
7 Garbage Collection and Stages ✅
8 Files and Streams ✅
9 Delegates and Events ✅

Powered by Claude Exporter 363/382


# Topic Status

10 Attributes ✅
11 I/O in C# and Windows Applications ✅
What's next?

Say "Unit 3 PYQs" for question analysis 🎯


Say "Unit 4 start" to keep moving 🚀
Say "last night revision Unit 3" for compressed notes 📝
What do you want to do Tannu? 😄
6/14/2026, 10:54:20 AM

Powered by Claude Exporter 364/382


yes pyq time que thatare new and not covered
don't miss any question

6/14/2026, 11:35:21 AM

Let me scan EVERY Unit 3 PYQ carefully against what we covered! 🔍


Scanning All Unit 3 PYQs...
J-21 Q6a — Write a program in C# for exception handling
→ Topic 6 ✅
J-21 Q6b — Discuss base class libraries. How is debugging implemented in .NET?
→ Base class libraries = Unit 1 Topic 3 ✅
→ "How is debugging implemented in .NET?" → CLR Debugger = Unit 1 Topic 8 ✅
J-21 Q7a — Write short notes on Delegates
→ Topic 9 ✅
J-21 Q7b — Write short notes on ICDLL files
→ Topic 1 (ICDLL covered inside DLL topic) ✅
M-23 Q6a — Explain files and streams with example
→ Topic 8 ✅
M-23 Q6b — Explain arrays and strings
→ Topic 4 ✅
M-23 Q7a — What is garbage collection? Stages? Why important?
→ Topic 7 ✅
M-23 Q7b — What is Exception? Explain throw, try, catch with example
→ Topic 6 ✅
M-24 Q6a — What is GAC utility? Types installed? How installed/removed?
→ Topic 3 ✅
M-24 Q6b — What is boxing and unboxing? Explain with example
→ Topic 5 ✅
Powered by Claude Exporter 365/382
M-24 Q7a — What is Exception? Explain various methods of exception handling
→ Topic 6 ✅
M-24 Q7b — Define delegates. How distinguished from events? Usefulness?
→ Topic 9 ✅
Compulsory Questions — Unit 3 Relevant:
M-23 compulsory (i) — Write a note on metadata. How different from data?
→ Unit 1 Extra Topic ✅
M-23 compulsory (ii) — Define interface and why required?
→ Unit 2 Topic 9 ✅
M-23 compulsory (iii) — Explain catch and throw exception
→ Topic 6 ✅
M-23 compulsory (iv) — Explain GAC utility
→ Topic 3 ✅
M-23 compulsory (v) — Explain virtual directory. Why is it used?
→ ❗ NOT COVERED — NEW TOPIC!
M-23 compulsory (vi) — What is LINQ? Why is it needed?
→ ❗ NOT COVERED — NEW TOPIC!
M-23 compulsory (vii) — What is the use of command class in [Link]?
→ Unit 4 topic — will cover there

M-24 compulsory (i) — Differentiate between file and stream


→ Topic 8 ✅
M-24 compulsory (ii) — Write down structure of C# program
→ Unit 2 Topic 4 ✅
M-24 compulsory (iii) — What is LINQ? Why required?
→ ❗ NOT COVERED — NEW TOPIC! (asked TWICE!)
M-24 compulsory (iv) — What is use of connection class in [Link]?
→ Unit 4 topic — will cover there

M-24 compulsory (v) — Explain non-static members of a class


→ Unit 2 PYQ analysis ✅

Powered by Claude Exporter 366/382


M-24 compulsory (vi) — Explain term unboxing in C#
→ Topic 5 ✅
M-24 compulsory (vii) — What is managed code? Why used?
→ Unit 1 + Unit 2 ✅
❗ New Topics Found — 2 items:
1. Virtual Directory (M-23 compulsory v)

2. LINQ (M-23 compulsory vi + M-24 compulsory iii — asked TWICE!)

Let's cover both now! 👇


📌 Extra Topic A: Virtual Directory
EXAM DEFINITION
A Virtual Directory in the context of [Link] and IIS (Internet Information Services) is a
logical directory name that maps to a physical directory on the server's file system or even
on another server. It allows web applications to access files from different physical locations
using a consistent URL path — without exposing the actual file system structure to users.

CORE CONCEPT
Problem Without Virtual Directory

Without virtual directory:

Physical path:
C:\Users\Admin\Projects\CompanyApp\wwwroot\images\[Link]
URL would be:
[Link]

Exposes internal folder structure — security risk!

Long, ugly URLs

Tightly coupled to physical location

Solution With Virtual Directory

Powered by Claude Exporter 367/382


With virtual directory:

Physical path:
C:\Users\Admin\Projects\CompanyApp\wwwroot\images\[Link]
Virtual path: [Link]

Clean, logical URL

Physical location hidden — more secure

Can change physical location without changing URLs ✅


HOW VIRTUAL DIRECTORY WORKS

User types URL:


[Link]

IIS receives request

IIS looks up Virtual Directory mapping:
/images → C:\CompanyApp\wwwroot\images\

IIS serves file from physical path:
C:\CompanyApp\wwwroot\images\[Link]

File sent to user's browser

CREATING VIRTUAL DIRECTORY IN IIS


Method 1 — IIS Manager (GUI):

1. Open IIS Manager

2. Expand Sites → Select your website

3. Right-click → Add Virtual Directory

4. Enter Alias (virtual name): images

5. Enter Physical path: C:\CompanyApp\images

Powered by Claude Exporter 368/382


6. Click OK ✅
Method 2 — [Link]

<configuration>
<[Link]>
<compilation debug="true" targetFramework="4.8" />
</[Link]>
</configuration>

Method 3 — In [Link] Core ([Link])

[Link](new StaticFileOptions {
FileProvider = new PhysicalFileProvider(
[Link]([Link](), "MyImages")),
RequestPath = "/images" // virtual path
});
// Now /images/* maps to MyImages/* folder

VIRTUAL DIRECTORY vs VIRTUAL APPLICATION


Virtual Directory Virtual Application

What it is Folder mapping Full web app mapping

Has own config No — inherits parent Yes — own [Link]

Has own app pool No Yes

Purpose Serve files/content Host separate web app

Example /images → folder /admin → admin app

USE CASES OF VIRTUAL DIRECTORY


Shared Resources — Multiple websites sharing same images/CSS folder

Content from Different Drive — App on C:\ serving files from D:\

Powered by Claude Exporter 369/382


Legacy Integration — Point virtual dir to old system's files

Load Balancing — Virtual dir pointing to network share across servers

Security — Hide actual file system paths from users

WHY VIRTUAL DIRECTORY IS USED — Exam Points


1. Abstraction — Logical path hides physical location

2. Security — Actual server paths not exposed in URLs

3. Flexibility — Physical location can change without breaking URLs

4. Sharing — Multiple sites share same physical folder

5. Organization — Clean URL structure regardless of file system layout

6. Remote Content — Can map to UNC paths (\server\share)

FEATURES
Alias-Based — Virtual name (alias) maps to physical path

Inherits Permissions — Inherits parent site's security settings

IIS Managed — Configured through IIS Manager or config files

URL Friendly — Creates clean, logical URL structure

Cross-Drive Support — Can map to any drive or network location

DIAGRAM GUIDANCE
Draw: Virtual Directory Mapping Diagram

Left side: User Browser → URL: [Link]

Arrow to center: IIS Server

Inside IIS box: Virtual Directory Table

/images → C:\App\wwwroot\images

/docs → D:\SharedDocs

/css → C:\App\styles

Arrow from IIS to right: Physical File System with actual folders

Powered by Claude Exporter 370/382


Label: "IIS maps virtual path to physical path transparently"

⭐ Exam Answer for M-23 Compulsory (v)


"Explain virtual directory. Why is it used?"

Define virtual directory

Explain alias → physical path mapping

How to create in IIS

Why used — security, flexibility, abstraction

Virtual Directory vs Virtual Application table

Diagram

📌 Extra Topic B: LINQ (Language Integrated Query)


EXAM DEFINITION
LINQ (Language Integrated Query) is a powerful feature introduced in C# 3.0 and .NET
Framework 3.5 that provides a unified, SQL-like query syntax directly integrated into the
C# language for querying and manipulating data from various sources — including
collections, arrays, XML, databases, and more. LINQ allows developers to write type-safe
queries using familiar C# syntax rather than learning separate query languages for each
data source.

CORE CONCEPT
Before LINQ — Different query languages for each source:

Query SQL Database → use SQL


Query XML → use XPath/XQuery
Query Collections → use foreach loops with if conditions
Query Objects → manual iteration

With LINQ — One unified syntax for ALL sources:

Powered by Claude Exporter 371/382


// Same LINQ syntax works for ALL data sources!
var result = from item in dataSource
where [Link] > value
select item;

WHY LINQ IS NEEDED ⭐


1. Unified Query Model — One syntax for collections, XML, databases, objects

2. Type Safety — Errors caught at compile time — not runtime

3. IntelliSense Support — IDE provides autocomplete for queries

4. Readable Code — Queries express intent clearly like SQL

5. Reduced Code — Complex foreach+if chains replaced by clean queries

6. Strongly Typed — Returns strongly typed results — no casting needed

7. Deferred Execution — Query runs only when results are needed

TWO SYNTAX STYLES


Style 1 — Query Syntax (SQL-like)

int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

var evenNumbers = from n in numbers


where n % 2 == 0
orderby n descending
select n;

foreach (int n in evenNumbers)


[Link](n + " ");
// Output: 10 8 6 4 2

Style 2 — Method Syntax (Lambda-based) ⭐ More common!

Powered by Claude Exporter 372/382


var evenNumbers = numbers
.Where(n => n % 2 == 0)
.OrderByDescending(n => n)
.Select(n => n);

foreach (int n in evenNumbers)


[Link](n + " ");
// Output: 10 8 6 4 2

LINQ STANDARD QUERY OPERATORS ⭐


Filtering

int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// Where — filter elements


var evens = [Link](n => n % 2 == 0);
// Result: 2, 4, 6, 8, 10

Projection

// Select — transform elements


var squares = [Link](n => n * n);
// Result: 1, 4, 9, 16, 25...

// SelectMany — flatten nested collections


var words = new[] { "Hello World", "LINQ is great" };
var allWords = [Link](s => [Link](' '));
// Result: Hello, World, LINQ, is, great

Ordering

string[] names = {"Tannu", "Riya", "Aman", "Zara"};

Powered by Claude Exporter 373/382


var sorted = [Link](n => n);
// Result: Aman, Riya, Tannu, Zara

var sortedDesc = [Link](n => n);


// Result: Zara, Tannu, Riya, Aman

var byLength = [Link](n => [Link]);


// Result: Riya, Aman, Zara, Tannu

Aggregation

int[] nums = {1, 2, 3, 4, 5};

[Link]([Link]()); // 5
[Link]([Link]()); // 15
[Link]([Link]()); // 3
[Link]([Link]()); // 1
[Link]([Link]()); // 5

Element Access

[Link]([Link]()); // 1
[Link]([Link]()); // 5
[Link]([Link]()); // 1 (or 0 if empty)
[Link]([Link](2)); // 3

Quantifiers

[Link]([Link](n => n > 8)); // True


[Link]([Link](n => n > 0)); // True
[Link]([Link](5)); // True

Grouping

Powered by Claude Exporter 374/382


string[] fruits = {"Apple","Apricot","Banana","Blueberry","Cherry"};

var grouped = [Link](f => f[0]); // group by first letter

foreach (var group in grouped) {


[Link]([Link] + ": ");
foreach (var item in group)
[Link](item + " ");
[Link]();
}
// Output:
// A: Apple Apricot
// B: Banana Blueberry
// C: Cherry

Set Operations

int[] a = {1, 2, 3, 4, 5};


int[] b = {3, 4, 5, 6, 7};

var union = [Link](b); // 1,2,3,4,5,6,7


var intersect = [Link](b); // 3,4,5
var except = [Link](b); // 1,2
var distinct = [Link](); // removes duplicates

Join

var students = new[] {


new { Id = 1, Name = "Tannu" },
new { Id = 2, Name = "Riya" }
};

var marks = new[] {


new { StudentId = 1, Score = 88 },

Powered by Claude Exporter 375/382


new { StudentId = 2, Score = 92 }
};

var result = [Link](


marks,
s => [Link],
m => [Link],
(s, m) => new { [Link], [Link] }
);

foreach (var r in result)


[Link]($"{[Link]}: {[Link]}");
// Output:
// Tannu: 88
// Riya: 92

LINQ WITH OBJECTS — Complete Example

using System;
using [Link];
using [Link];

class Student {
public string Name { get; set; }
public int Age { get; set; }
public double Marks { get; set; }
public string City { get; set; }
}

class Program {
static void Main() {

List<Student> students = new List<Student> {


new Student { Name="Tannu", Age=21, Marks=88.5,
City="Delhi" },

Powered by Claude Exporter 376/382


new Student { Name="Riya", Age=20, Marks=92.0,
City="Mumbai" },
new Student { Name="Aman", Age=22, Marks=78.3,
City="Delhi" },
new Student { Name="Zara", Age=21, Marks=95.1,
City="Mumbai" },
new Student { Name="Raj", Age=23, Marks=65.0,
City="Delhi" }
};

// 1. Students with marks > 80


[Link]("--- High Scorers ---");
var topStudents = students
.Where(s => [Link] > 80)
.OrderByDescending(s => [Link]);

foreach (var s in topStudents)


[Link]($"{[Link]}: {[Link]}");

// 2. Students from Delhi


[Link]("\n--- Delhi Students ---");
var delhiStudents = [Link](s => [Link] == "Delhi")
.Select(s => [Link]);
foreach (var name in delhiStudents)
[Link](name);

// 3. Average marks
[Link]($"\nAverage Marks: {[Link](s =>
[Link]):F2}");

// 4. Group by city
[Link]("\n--- By City ---");
var byCity = [Link](s => [Link]);
foreach (var group in byCity) {
[Link]($"{[Link]}:");

Powered by Claude Exporter 377/382


foreach (var s in group)
[Link]($" {[Link]} - {[Link]}");
}

// 5. Top scorer
var topper = [Link](s =>
[Link]).First();
[Link]($"\nTopper: {[Link]}
({[Link]})");
}
}

Output:

--- High Scorers ---


Zara: 95.1
Riya: 92.0
Tannu: 88.5

--- Delhi Students ---


Tannu
Aman
Raj

Average Marks: 83.78

--- By City ---


Delhi:
Tannu - 88.5
Aman - 78.3
Raj - 65.0
Mumbai:
Riya - 92.0
Zara - 95.1

Powered by Claude Exporter 378/382


Topper: Zara (95.1)

TYPES OF LINQ
Type Data Source Namespace

LINQ to Objects Collections, Arrays [Link]

LINQ to SQL SQL Server Database [Link]

LINQ to XML XML documents [Link]

LINQ to Entities Entity Framework [Link]

LINQ to DataSet [Link] DataSet [Link]

DEFERRED EXECUTION ⭐ Important!


LINQ queries don't execute immediately — they execute when iterated:

int[] nums = {1, 2, 3, 4, 5};

// Query defined — NOT executed yet


var query = [Link](n => n > 2);

// Modify source
nums[0] = 10;

// Query executes NOW — reflects modification!


foreach (int n in query)
[Link](n + " ");
// Output: 10 3 4 5 (not 3 4 5 as you might expect!)

// Force immediate execution:


var immediate = [Link](n => n > 2).ToList(); // executed now
var array = [Link](n => n > 2).ToArray(); // executed now

Powered by Claude Exporter 379/382


LINQ QUERY SYNTAX vs METHOD SYNTAX
Query Syntax Method Syntax

Style SQL-like keywords Method chains with lambdas

Readability More readable for complex queries Concise for simple queries

Keywords from, where, select, orderby .Where(), .Select(), .OrderBy()

All operators Not all supported All operators available

Preference Beginners Experienced developers

ADVANTAGES OF LINQ
Unified — One syntax for all data sources

Type-Safe — Compile-time error checking

Readable — Clear, expressive query code

Less Code — Replaces verbose foreach+if patterns

IntelliSense — Full IDE support

Composable — Chain multiple operations

Testable — Easy to unit test LINQ queries

DISADVANTAGES
Performance — Can be slower than hand-optimized SQL

Debugging — Lambda chains harder to debug than loops

Learning Curve — Deferred execution confuses beginners

Overuse — Complex LINQ can be harder to read than simple loops

DIAGRAM GUIDANCE
Draw: LINQ Architecture Diagram

Left column — Data Sources:

Collections/Arrays

Powered by Claude Exporter 380/382


SQL Database

XML Documents

Entity Framework

Center: LINQ Query Engine (with lambda/query syntax)

Right: Strongly Typed Results

Label: "One unified query syntax for all data sources"

Draw: LINQ Method Chain

dataSource
.Where(filter condition)
.OrderBy(sort key)
.Select(transform)
.ToList()

Show as pipeline with arrow between each step

⭐ Exam Answer for M-23 + M-24 Compulsory


"What is LINQ? Why is it needed?"

✅ Definition
✅ Why needed — unified query, type safety, readability
✅ Two syntax styles with example
✅ Common operators — Where, Select, OrderBy, GroupBy
✅ Types of LINQ table
✅ Deferred execution explanation
✅ Advantages
✅ Diagram
✅ Unit 3 NOW 100% Complete!
Topic Source Status

Topics 1-11 Syllabus ✅

Powered by Claude Exporter 381/382


Topic Source Status

Virtual Directory M-23 PYQ ✅


LINQ M-23 + M-24 PYQ ✅
Unit 3 — fully exam ready! 🎉
What's next?

Say "Unit 4 start" 🚀


Say "last night revision Unit 3" 📝
What do you want Tannu? 😄
6/14/2026, 11:36:49 AM

Powered by Claude Exporter 382/382

You might also like