C# Essentials for Developers
1. What is C#?
C# is a computer programming language. C# was developed by Microsoft in 2000 to provide a modern general-purpose programming language that can be used to develop all kinds of software targeting various platforms including Windows, Web, and Mobile using just one programming language. Today, C# is one of the most popular programming languages in the world. Millions of software developers use C# to build all kinds of software.
C# is the primary language for building Microsoft .NET software applications. Developers can build almost every kind of software using C# including Windows UI apps, console apps, backend services, cloud APIs, Web services, controls and libraries, serverless applications, Web applications, native iOS and Android apps, AI and machine learning software, and blockchain applications.
C# with the help of Visual Studio IDE provides rapid application development. C# is a modern, object-oriented, simple, versatile, and performance-oriented programming language. C# is developed based on the best features and use cases of several programming languages including C++, Java, Pascal, and SmallTalk.
C# syntaxes are like C++. .NET and the C# library is similar to Java. C# supports modern object-oriented programming language features including Abstraction, Encapsulation, Polymorphism, and Inheritance. C# is a strongly typed language and most types are inherited by the Object class.
C# supports concepts of classes and objects. Classes have members such as fields, properties, events, and methods. Here is a detailed article on C# and OOP.
C# is versatile, modern, and supports modern programming needs. Since its inception, C# language has gone through various upgrades. The latest version of C# is v12.0.
Lets Jump in..
2. Data types & Variables
C# Data Types :
C# is a strongly typed language, which means every variable must have a data type declared (explicitly/clearly or implicitly/not direct)
Value Types (stored on stack)- Store actual data.
int, double, float
bool, char
struct, enum
Reference Types (stored on heap)- Store reference (address) to data.
string, object, dynamic
Arrays (int[], string[])
Classes, Interfaces, Delegates
Variables
A variable is a name that stores data that can change during program execution.
Declaring variables:
Naming Rules :
Can contain letters, digits, and underscores.
Must start with a letter or _.
Cannot be a C# keyword (int, class, etc.).
Should be camelCase by convention for local variables.
User-defined Value Types
An enum is a special "value type" that lets you define a set of named constants.
It improves code readability and helps you avoid using magic numbers or hard-coded values.
Behind the scenes, each name is mapped to an integer (starting from 0 by default).
Usage:
Key Features
Common Uses
Status codes
Modes (e.g., ReadMode, WriteMode)
States (e.g., State.Idle, State.Running)
Days, categories, types, etc.
Converting Enums
3.Operators
Operators are symbols used to perform operations on variables and values.
Arithmetic operators
Assignment Operators
Comparison (Relational) Operators
Used in conditions (if, loops).
Logical Operators
Used to combine conditions.
Unary Operators
Operate on a single operand.
Ternary Operator
A shorthand for if-else.
Null-Coalescing Operators
Helps with null handling.
Example Combining All
4. Control structures
Control structures in C# are flow control mechanisms that:
1. Conditional Statements
if, else if, else
Used to execute code based on conditions.
Switch
Use break to avoid falling through to the next case.
C# 8+ supports switch expressions for more concise syntax:
2. Looping Statements
for loop
Used when the number of iterations is known.
while loop
Executes as long as the condition is true.
do...while loop
Similar to while, but executes at least once.
foreach loop
Used to iterate over collections like arrays, lists, etc.
3. Jump Statements (break, continue, return)
break
Exits the current loop or switch.
continue
Skips the current iteration and continues the next one.
return
Exits the method and optionally returns a value.
5. Object oriented programming (OOP)
OOP is a programming paradigm that uses objects and classes to design software.
C# is a fully object-oriented language, so understanding OOP is essential for writing clean, modular, and maintainable code.
Classes and Objects
Class: Blueprint of an object.
Object: Instance of a class (created with new keyword).
Methods and Properties
A method is a block of code that performs a specific task. It belongs to a class and can return a value or be void.
Types of Methods:
Instance Methods: Belong to an object (obj.Method()).
Static Methods: Belong to the class (Class.Method()).
Properties
A property is a class member that provides a flexible mechanism to read, write, or compute the value of a private field
Auto-Implemented Property:
C# allows you to write short-hand for simple get/set:
You can also define read-only or write-only properties:
Keywords in C#
static
Used to declare members or methods that belong to the class, not instances.
Called on the class directly without new.
When to use:
Utility/helper classes
Shared data (e.g., counters, constants)
readonly
Applies to fields, ensures they can only be assigned:
at declaration, or
inside a constructor
const
Used for compile-time constants
Must be assigned immediately
virtual, override, abstract, sealed (used in inheritance)
virtual
Allows a method or property to be overridden in derived class.
override
Used in a derived class to override a base class method/property.
abstract
Defines a method/property without implementation. Must be overridden in derived class.
Can only be declared in abstract classes.
sealed
Prevents a class from being inherited, or a method from being overridden further.
Encapsulation
Encapsulation is the process of bundling data (fields) and methods that operate on the data, into a single unit (class), and restricting access using access modifiers.
Access is controlled via public methods (Deposit, GetBalance), not directly.
Abstraction
Abstraction hides internal implementation and exposes only what is necessary
User just calls MakeSound(), not worrying how it’s implemented.
Inheritance
Inheritance allows a class (child) to inherit fields and methods from another class (parent).
Polymorphism
Polymorphism means “many forms”. In C#, there are two types:
a) Compile-Time Polymorphism (Method Overloading)
Same method name, different signatures.
b) Run-Time Polymorphism (Method Overriding using virtual / override)
Which method runs is decided at runtime, depending on the actual object
Access Modifiers:
public
The least restrictive modifier.
Members marked public can be accessed from any class, any namespace, any assembly.
private (Default for class members)
Most restrictive.
Members are accessible only within the class where they are declared.
protected
Accessible within the same class and its derived (child) classes.
Not accessible from outside unless you're inheriting.
internal
Accessible anywhere within the same assembly/project.
Not accessible from another project (DLL).
➡️ You can access this class from anywhere within the same project, but not from a referenced project.
protected internal
Accessible in derived classes anywhere OR within the same assembly.
Combines protected + internal.
➡️ Usable from:
Any class in the same assembly.
Derived classes from other assemblies.
private protected (C# 7.2+)
Accessible in:
Same class
Derived classes in the same assemblyNot accessible in derived classes from a different assembly.
Combined example:
public class Person
ssn: Only within Person
nationality: Accessible in Person and its subclasses
email: Accessible in any class in the same project
address: Accessible in subclasses or same project
bankAccount: Accessible only in subclasses in same project
6. Interfaces And Abstract classes
They're both used for abstraction, but they serve slightly different purposes.
Interfaces
An interface is a contract that only contains method signatures (no implementation). A class or struct that implements the interface must provide implementations for all of its members.
Implementing an interface
Key Points:
No fields or constructors allowed
Can have default implementations (C# 8+)
A class can implement multiple interfaces
Used for polymorphism and loose coupling
Example of polymorphism
Abstract Classes
An abstract class is a partially implemented class that can have both abstract (unimplemented) and non-abstract (implemented) members.
You cannot instantiate an abstract class directly.
Syntax
Derived class:
Key Points:
Can include fields, constructors, methods, properties
Use when you want to provide shared base functionality
Only one abstract base class per class (single inheritance)
Interface + Abstract Class Together
When to Use What?
Real-World Analogy
Interface: Like a remote control interface — different brands implement it (TV, AC) but the interface defines what buttons exist.
Abstract Class: Like a base machine blueprint — defines what all machines have in common and allows each machine to fine-tune.
7. Arrays and Collections
Arrays
An array in C# is a fixed-size, strongly typed data structure used to store a sequence of elements of the same type.
Examples:
Collections
Collections provide dynamic storage — unlike arrays, they can grow or shrink in size and offer more functionality like searching, sorting, and filtering.
Generic Collections (Recommended)
Found in System.Collections.Generic
List<T> – Dynamic array
Dictionary<TKey, TValue> – Key-value store
HashSet<T> – Unique unordered values
Queue<T> – FIFO (First In First Out)
Stack<T> – LIFO (Last In First Out)
Generic collection Interfaces
Use cases and implementation
IEnumerable<T>
Enables foreach loops.
Base for LINQ queries.
IEnumerator<T>
Used internally by IEnumerable<T> to move through the collection.
Has methods like .MoveNext(), .Reset(), .Current.
ICollection<T>
Adds collection-wide operations:
Count, Add, Remove, Clear, Contains
IList<T>
Allows indexed access ([index]) and insertion/removal at specific positions.
IDictionary<TKey, TValue>
Key-value pairs.
Has methods like Add(key, value), ContainsKey, TryGetValue.
ISet<T>
Ensures uniqueness of elements.
No duplicates allowed.
IReadOnlyCollection<T>, IReadOnlyList<T>, IReadOnlyDictionary<TKey, TValue>
Immutable views of collections.
Safe to expose in APIs to prevent modification.
IComparer<T> / IEqualityComparer<T>
Custom sorting or equality logic.
Example: Sorting people by age
Example: Custom equality for HashSet
What is IQueryable<T>?
It’s an interface from System.Linq.
What It Means:
IQueryable<T> is used mostly with remote data sources (like databases).
It supports deferred execution and translates LINQ queries into SQL or other expressions (e.g., EF Core, LINQ to SQL).
Query is not executed until you enumerate it (e.g., ToList() or foreach).
Real-World Analogy
List<T> is like a bookshelf — it stores books (data).
IEnumerable<T> is like saying, "I can walk along this shelf and look at each book."
IQueryable<T> is like saying, "Tell the librarian to fetch books where author = 'Faizal'."
Non-Generic Collections (Older, less used)
Stored as object, so boxing/unboxing required:
ArrayList: Like List<object>
Hashtable: Like Dictionary<object, object>
Queue, Stack (non-generic versions)
🔍 Avoid unless maintaining legacy code.
LINQ with Collections
C# supports LINQ queries on collections:
Interfaces:
Concurrent Collections (for multithreading)
ConcurrentDictionary<TKey, TValue>
ConcurrentQueue<T>
ConcurrentBag<T>
Used when multiple threads need to access the collection safely.
Choosing the Right Collection
Interfaces
Example Combining Them
Custom Collection Class (Advanced)
You can also create your own collection class by implementing:
IEnumerable<T> (for iteration)
ICollection<T> (for add/remove/count)
IDictionary<K,V> (for key-value stores)
Array vs Collection
Are Arrays Collections?
Not exactly — but close.
Arrays are not part of the System.Collections namespace, so technically they're not "collections" in the same way as List<T> or Dictionary<K,V>.
However, arrays do implement:
IEnumerable (non-generic)
IEnumerable<T> (generic)
So they can be used with LINQ and foreach loops, just like collections.
Arrays behave like collections, but they are not part of the .NET Collections Framework.
Array vs Collection Comparison
Example: Using Array in a foreach Loop
When to Use Arrays vs Collections
Pro Tip
In most real-world C# applications:
Use arrays when performance matters and size is fixed.
Use List<T> when working with dynamic data
8. Delegates, Events, and Lambdas
Delegates
A delegate is a type-safe function pointer — it can hold a reference to a method with a specific signature.
Use Cases:
Callback methods
Event handling
Plug-in patterns
Multicast Delegates
Delegates can hold multiple methods — they’re invoked in order.
Events
An event is a wrapper over delegates. It provides a publisher-subscriber model, commonly used in UI or real-time systems.
Subscribing to Events:
Lambda Expressions
A lambda is an anonymous method (a function without a name) written using the => syntax.
Example:
Built-in Delegates
To avoid defining custom delegate types every time, C# provides these predefined generic delegates:
Func<T>
Returns a value
Can take 0 to 16 parameters
Last generic type is the return type
Action<T>
Returns void
Can take 0 to 16 parameters
Predicate<T>
Returns a bool
Takes exactly 1 parameter
Comparison Table
Real-World Use Example:
Bonus: Event with Built-in Delegate
9. LINQ (Language Integrated Query)
What is LINQ?
LINQ (Language Integrated Query) allows you to query collections (arrays, lists, XML, databases, etc.) using a SQL-like syntax — but in C#.
It integrates query capabilities directly into C# through extension methods and lambda expressions.
Where You Can Use LINQ
Arrays
List<T>, Dictionary<K,V>, HashSet<T>, etc.
XML (System.Xml.Linq)
SQL databases (via LINQ to Entities / LINQ to SQL)
JSON or in-memory objects
Two LINQ Syntaxes
1. Query Syntax (SQL-like):
2. Method Syntax (Fluent, Lambda-based):
Both are functionally equivalent — method syntax is more common in real-world C# apps.
Example with List<int>
Common LINQ Methods (with Lambdas)
Real-World Example: Working with Objects
LINQ Behind the Scenes
LINQ uses deferred execution:
The query isn't executed until you iterate or call ToList(), First(), etc.
Helps with performance when working with large datasets or databases.
LINQ in Databases: LINQ to Entities
If you're using Entity Framework, you can write:
EF will translate it into SQL behind the scenes!
Benefits of LINQ
Clean and readable code
Type safety (compile-time checks)
IntelliSense support in IDE
Works across data types (objects, XML, SQL, JSON)
Summary
10. Exception Handling
Exception handling is a mechanism to catch and handle runtime errors in a structured and safe way, without crashing the application.
C# provides a robust exception handling model using:
Why Exception Handling?
Prevents program crashes due to unexpected situations.
Helps maintain application stability and user experience.
Enables logging and error tracking.
Keeps business logic separate from error-handling logic.
Basic Syntax
Keywords Explained
Example: Throwing Custom Exceptions
Common Exceptions in C#
Custom Exception Class (Advanced)
Use it like:
Best Practices
✅ Catch specific exceptions first
✅ Avoid empty catch blocks
✅ Use finally for cleanup
✅ Use custom exceptions for domain-specific errors
✅ Don't catch exceptions you can't handle
✅ Log errors for diagnostics
When to Use try-catch
11. Garbage Collection & Memory Management
Garbage Collection (GC) in C# is an automatic memory management system provided by the .NET runtime.
It:
Reclaims memory used by objects that are no longer accessible.
Frees developers from manual memory allocation and deallocation (like in C/C++).
Helps prevent memory leaks and dangling pointers.
Key Concepts
How Garbage Collector Works
Process:
GC marks objects that are still in use.
It sweeps and removes unused objects.
It compacts memory by shifting live objects together.
This improves memory efficiency and performance.
When does GC run?
When system memory is low
When Gen 0 or Gen 1 thresholds are hit
When you call GC.Collect() (not recommended unless absolutely necessary)
IDisposable and using Statement
For objects using unmanaged resources (like files, database connections), C# uses:
IDisposable interface:
using block:
Weak References
Allows the GC to collect the object even if you still have a reference.
Useful for caching scenarios.
Finalizers (Destructors)
If you can't use IDisposable, define a finalizer:
⚠ Finalizers slow down GC and should be avoided unless absolutely needed.
Best Practices
✅ Use using for IDisposable objects
✅ Avoid unnecessary object creation
✅ Don’t call GC.Collect() unless required
✅ Prefer composition over inheritance for large objects
✅ Be cautious with static references (they survive until app exits)
Comments
Post a Comment