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