Learning C# Programming
Master modern .NET development with C# - from enterprise applications to Unity games. Build cross-platform applications with one of the most powerful and elegant languages.
Why Learn C#?
- Enterprise Ready: C# powers millions of business applications with robust frameworks like ASP.NET Core and Entity Framework
- Unity Game Development: The primary language for Unity, the world's most popular game engine used by 50% of all games
- Cross-Platform Power: Build for Windows, Linux, macOS, iOS, Android, and web with .NET 8 and MAUI
- Modern Language Features: Async/await, LINQ, pattern matching, records, and top-level statements for clean, expressive code
- Career Opportunities: High demand for C# developers in enterprise, game development, and cloud infrastructure roles
Your Learning Path
Master C# step-by-step with this progressive curriculum:
2-3 hours
3-4 hours
2-3 hours
3-4 hours
2 hours
2 hours
3-4 hours
Interactive Lessons
Click each lesson to expand. Mark complete as you learn.
Variables, Types & Nullable Types
C# has a unified type system where everything derives from object. Understanding value types, reference types, and nullable types is crucial for writing safe, efficient code.
Value Types vs Reference Types
- Value types (int, double, bool, struct) store data directly on the stack
- Reference types (string, class, array) store a reference to heap-allocated data
- Boxing/Unboxing: Converting value types to object incurs performance cost
// Value types
int age = 25;
double pi = 3.14159;
bool isActive = true;
// Reference types
string name = "Alice";
int[] numbers = { 1, 2, 3, 4, 5 };
// Nullable types (C# 2.0+)
int? nullableAge = null;
if (nullableAge.HasValue)
{
Console.WriteLine($"Age: {nullableAge.Value}");
}
else
{
Console.WriteLine("Age not specified");
}
// Null-coalescing operator
int displayAge = nullableAge ?? 0;
// C# 8.0: Nullable reference types
string? possiblyNullName = null; // Explicitly nullable
string guaranteedName = "Bob"; // Never null (compiler warns)
The var Keyword
C# supports type inference with var. The type is determined at compile time:
var count = 10; // int
var price = 99.99; // double
var message = "Hello"; // string
var items = new List<string>(); // List<string>
Object-Oriented Programming
C# is a fully object-oriented language with first-class support for classes, inheritance, polymorphism, and interfaces.
Classes and Properties
public class Person
{
// Auto-implemented properties
public string Name { get; set; }
public int Age { get; set; }
// Property with backing field
private string _email;
public string Email
{
get => _email;
set => _email = value?.ToLower();
}
// Read-only property (C# 6.0+)
public string FullInfo => $"{Name} ({Age})";
// Constructor
public Person(string name, int age)
{
Name = name;
Age = age;
}
// Method
public void Introduce()
{
Console.WriteLine($"Hi, I'm {Name}");
}
}
Inheritance and Polymorphism
public class Employee : Person
{
public string JobTitle { get; set; }
public Employee(string name, int age, string jobTitle)
: base(name, age)
{
JobTitle = jobTitle;
}
// Override base method
public override string ToString()
{
return $"{Name} - {JobTitle}";
}
}
LINQ & Collections
LINQ (Language Integrated Query) lets you query collections with SQL-like syntax. It's one of C#'s most powerful features.
var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Query syntax
var evenQuery = from n in numbers
where n % 2 == 0
select n;
// Method syntax (preferred in most cases)
var evenMethod = numbers.Where(n => n % 2 == 0);
// Chaining operations
var result = numbers
.Where(n => n > 3)
.Select(n => n * 2)
.OrderByDescending(n => n)
.ToList();
// Aggregations
int sum = numbers.Sum();
double average = numbers.Average();
int max = numbers.Max();
// GroupBy
var groups = numbers.GroupBy(n => n % 2 == 0 ? "Even" : "Odd");
Async/Await & Task-based Programming
Async/await makes asynchronous programming natural and readable. Essential for I/O-bound operations.
public async Task<string> FetchDataAsync(string url)
{
using var client = new HttpClient();
// await frees up the thread while waiting
string result = await client.GetStringAsync(url);
return result;
}
// Using the async method
public async Task ProcessDataAsync()
{
string data = await FetchDataAsync("https://api.example.com");
Console.WriteLine(data);
}
// Running multiple tasks concurrently
public async Task<int> ProcessMultipleAsync()
{
var task1 = FetchDataAsync("url1");
var task2 = FetchDataAsync("url2");
var task3 = FetchDataAsync("url3");
// Wait for all to complete
await Task.WhenAll(task1, task2, task3);
return task1.Result.Length + task2.Result.Length + task3.Result.Length;
}
Generics & Constraints
Generics let you write flexible, reusable code that works with any type while maintaining type safety.
// Generic class
public class Stack<T>
{
private List<T> items = new List<T>();
public void Push(T item) => items.Add(item);
public T Pop()
{
var item = items[^1];
items.RemoveAt(items.Count - 1);
return item;
}
}
// Generic method with constraints
public T FindMax<T>(List<T> items) where T : IComparable<T>
{
if (items.Count == 0) throw new InvalidOperationException();
T max = items[0];
foreach (var item in items)
{
if (item.CompareTo(max) > 0)
max = item;
}
return max;
}
Delegates, Events & Pattern Matching
Delegates and events enable loose coupling and event-driven architectures. Pattern matching provides concise type checking.
// Delegate
public delegate void NotifyHandler(string message);
// Event
public class Process
{
public event NotifyHandler OnComplete;
public void Run()
{
// Do work...
OnComplete?.Invoke("Process complete");
}
}
// Pattern matching (C# 7.0+)
public string Describe(object obj) => obj switch
{
int n when n > 0 => "Positive number",
int n when n < 0 => "Negative number",
string s => $"String of length {s.Length}",
null => "Null value",
_ => "Something else"
};
// Records (C# 9.0+) - immutable data holders
public record Person(string Name, int Age);
Curated GitHub Repositories
Hand-picked repositories to accelerate your C# learning journey.
Practice Projects
-
1. Console Calculator with Exception Handling
Build a command-line calculator with proper input validation and exception handling.
Key Concepts: variables, methods, try/catch, Console I/O -
2. Todo List with LINQ Filtering
Create a console-based todo manager using collections and LINQ for filtering/sorting.
Key Concepts: Lists, LINQ, file I/O, object serialization -
3. Weather API Client with Async/Await
Build an HTTP client that fetches weather data asynchronously and displays formatted results.
Key Concepts: HttpClient, async/await, JSON deserialization, error handling -
4. ASP.NET Core REST API
Create a RESTful API with CRUD operations, Entity Framework Core, and dependency injection.
Key Concepts: Web APIs, EF Core, repositories, middleware, authentication -
5. Unity 2D Platformer Prototype
Build a 2D platformer game in Unity with player movement, collision detection, and scoring.
Key Concepts: Unity scripting, MonoBehaviour, physics, game loops, prefabs
Resources Hub
Official Docs
️ Practice
Community
Your Progress
Check off lessons as you complete them. Your progress is saved locally in your browser.