C# Version History
Understanding C# versions helps you know which features are available on your target .NET version and why certain patterns exist.
Quick Reference
| C# Version | .NET Version | Year | Key Features |
|---|---|---|---|
| C# 1.0 | .NET 1.0 | 2002 | Classes, interfaces, delegates, events |
| C# 2.0 | .NET 2.0 | 2005 | Generics, nullable value types, iterators, anonymous methods |
| C# 3.0 | .NET 3.5 | 2007 | LINQ, lambda expressions, var, extension methods, object initializers |
| C# 4.0 | .NET 4.0 | 2010 | Dynamic typing, named/optional parameters, covariance |
| C# 5.0 | .NET 4.5 | 2012 | async/await, caller info attributes |
| C# 6.0 | .NET 4.6 | 2015 | String interpolation, null-conditional ?., nameof, expression bodies |
| C# 7.0 | .NET 4.7 | 2017 | Tuples, pattern matching, out variables, local functions |
| C# 7.1-7.3 | .NET 4.7.x | 2017-18 | Async Main, default literals, pattern matching improvements |
| C# 8.0 | .NET Core 3.0 | 2019 | Nullable refs, switch expression, using declaration, async streams |
| C# 9.0 | .NET 5 | 2020 | Records, init-only, top-level statements, pattern matching enhancements |
| C# 10.0 | .NET 6 LTS | 2021 | Global usings, file-scoped namespaces, record structs, const interpolated strings |
| C# 11.0 | .NET 7 | 2022 | Required members, raw strings, list patterns, generic attributes |
| C# 12.0 | .NET 10 LTS | 2023 | Primary constructors, collection expressions, alias any type, inline arrays |
| C# 13.0 | .NET 9 | 2024 | params collections, new Lock type, field keyword, partial properties |
| C# 14.0 | .NET 10 LTS | 2025 | Extensions, field keyword stable, unmanaged generics improvements |
| C# future | .NET 10+ | 2026 | Continued performance, AI integration patterns |
C# 1.0 - 2002 (.NET 1.0)
Foundation - OOP language basics
// Classes, objects, interfaces, delegates - everything we built in this series
public class Student
{
private string _name;
public string Name { get { return _name; } set { _name = value; } }
public Student(string name) { _name = name; }
public void Display() { Console.WriteLine(_name); }
}
public interface IGradable { string GetGrade(); }
public delegate void NotifyHandler(string message);
C# 2.0 - 2005 (.NET 2.0)
Generics, nullable types, iterators
// Generics - type-safe collections
List<Student> students = new List<Student>();
Dictionary<string, int> marks = new Dictionary<string, int>();
// Nullable value types
int? optionalAge = null;
bool? isEnrolled = null;
// Iterators - yield return
public IEnumerable<Student> GetPassed()
{
foreach (var s in _students)
if (s.Percentage >= 35)
yield return s;
}
// Anonymous methods (before lambdas)
students.ForEach(delegate(Student s) { Console.WriteLine(s.Name); });
C# 3.0 - 2007 (.NET 3.5)
LINQ, lambda, var, extension methods, object initializers - Big release
// var - type inference
var students = new List<Student>();
var name = "Sahasra Kumar";
// Lambda expressions
Func<Student, bool> passed = s => s.Percentage >= 35;
// Object initializers
var s = new Student { Name = "Sahasra", ClassName = "10th", Percentage = 87.5 };
// LINQ
var topStudents = students
.Where(s => s.Percentage >= 90)
.OrderByDescending(s => s.Percentage)
.Select(s => new { s.Name, s.Percentage })
.ToList();
// Extension methods
public static bool HasPassed(this Student s) => s.Percentage >= 35;
C# 4.0 - 2010 (.NET 4.0)
Dynamic, named/optional parameters, covariance
// Optional parameters - no overloads needed
void Enroll(string name, string className = "1st", bool isActive = true) { }
Enroll("Sahasra");
Enroll("Priya", className: "10th"); // named arguments
// Dynamic - type resolved at runtime
dynamic student = GetStudentFromJson();
Console.WriteLine(student.Name); // no compile check
C# 5.0 - 2012 (.NET 4.5)
async/await - Game-changing
// async/await - non-blocking I/O
public async Task<List<Student>> GetStudentsAsync()
{
await Task.Delay(100); // simulate DB call - thread not blocked
return _students;
}
// Caller info attributes
public void Log(string message,
[CallerMemberName] string member = "",
[CallerFilePath] string file = "",
[CallerLineNumber] int line = 0)
{
Console.WriteLine($"[{file}:{line}] {member}: {message}");
}
C# 6.0 - 2015 (.NET 4.6)
String interpolation, null-conditional, expression bodies
// String interpolation
Console.WriteLine($"Student: {student.Name}, Grade: {student.GetGrade()}");
// Null-conditional operator
string? upper = student?.Name?.ToUpper();
int? len = student?.Name?.Length;
// Expression-bodied members
public string FullName => $"{FirstName} {LastName}";
public bool HasPassed => Percentage >= 35;
public string GetGrade() => Percentage >= 90 ? "A+" : "Pass";
// nameof
throw new ArgumentNullException(nameof(student));
// Index initializers
var marks = new Dictionary<string, int>
{
["Maths"] = 91,
["Science"] = 85,
};
C# 7.0 - 2017 (.NET 4.7)
Tuples, pattern matching, out variables, local functions
// Tuples
var (passed, grade, pct) = GetResult(marks);
(string name, double pct) student = ("Sahasra", 87.5);
// Pattern matching
if (member is Student s && s.Percentage >= 90)
Console.WriteLine($"Top student: {s.Name}");
// out variable inline
if (int.TryParse(input, out int marks))
Console.WriteLine($"Valid: {marks}");
// Local functions
double GetAverage()
{
return Calculate(); // local function
double Calculate() => marks.Average();
}
// throw expressions
string name = input ?? throw new ArgumentNullException(nameof(input));
C# 8.0 - 2019 (.NET Core 3.0)
Nullable reference types, switch expression, using declarations, ranges
// Nullable reference types (enable in .csproj)
string name = "Sahasra"; // non-nullable - warning if assigned null
string? middleName = null; // explicitly nullable
// Switch expression
string grade = percentage switch
{
>= 90 => "A+",
>= 80 => "A",
_ => "Fail"
};
// using declaration
using var writer = new StreamWriter("file.txt"); // Dispose at end of scope
// Ranges and indices
string[] subjects = { "Maths", "Science", "English", "Social", "Hindi" };
var last2 = subjects[^2..]; // last 2
var first3 = subjects[..3]; // first 3
var middle = subjects[1..4]; // index 1 to 3
// Async streams
async IAsyncEnumerable<Student> GetStudentsAsync()
{
foreach (var s in await LoadAsync())
yield return s;
}
C# 9.0 - 2020 (.NET 5)
Records, init-only, top-level statements, pattern improvements
// Records - immutable data with value equality
public record StudentRecord(int Id, string Name, string ClassName, double Percentage);
var rec = new StudentRecord(1, "Sahasra", "10th", 87.5);
var updated = rec with { ClassName = "11th" }; // non-destructive mutation
Console.WriteLine(rec == updated); // False
// init-only properties
public class Student
{
public int Id { get; init; } // set only in object initializer
public string Name { get; init; } = "";
}
// Top-level statements
// Program.cs no longer needs class/Main
Console.WriteLine("School Management System");
// Pattern matching improvements
if (student is { Percentage: >= 90, FeesPaid: true })
Console.WriteLine("Scholar");
C# 10.0 - 2021 (.NET 6)
Global usings, file-scoped namespaces, record structs
// Global usings - in GlobalUsings.cs
global using System;
global using System.Linq;
global using System.Collections.Generic;
// File-scoped namespace - no extra indent
namespace SchoolManagement.Services;
public class StudentService { /* no extra indent level */ }
// Record structs - immutable value type
public record struct Point(int X, int Y);
// Extended property patterns
if (student is { Address.City: "Hyderabad" })
Console.WriteLine("Local student");
// Constant interpolated strings
const string Prefix = "NCA";
const string Format = $"{Prefix}-2024"; // C# 10 only
C# 11.0 - 2022 (.NET 7)
Required members, raw strings, list patterns, generic attributes
// required members - compiler error if not set
public class Student
{
public required int Id { get; set; }
public required string Name { get; set; }
public string Section { get; set; } = "A";
}
var s = new Student { Id=1, Name="Sahasra" }; // OK
// var s2 = new Student { Id=1 }; // [X] Name required
// Raw string literals
string json = """
{
"name": "Sahasra Kumar",
"class": "10th",
"percentage": 87.5
}
""";
// List patterns
int[] marks = { 91, 85, 78 };
if (marks is [>= 80, >= 80, ..]) Console.WriteLine("First two above 80");
// Generic attributes
public class ValidateAttribute<T> : Attribute where T : IValidator { }
C# 12.0 - 2023 (.NET 10)
Primary constructors, collection expressions, alias types
// Primary constructors - no boilerplate
public class StudentService(IStudentRepository repo, ILogger<StudentService> logger)
{
public async Task<Student?> GetAsync(int id)
{
logger.LogInformation("Getting student {Id}", id);
return await repo.GetByIdAsync(id);
}
}
// Collection expressions - unified syntax
int[] marks = [91, 85, 78];
List<string> subjects = ["Maths", "Science", "English"];
Span<int> scores = [91, 85, 78];
// Spread operator
int[] extra = [95, 88];
int[] all = [..marks, ..extra]; // combine
// Inline arrays (performance)
[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer { private int _element; }
// Alias any type
using StudentId = int;
using GradeMap = Dictionary<string, double>;
C# 13.0 - 2024 (.NET 9)
params collections, new lock, field keyword
// params with any collection type (not just arrays)
void PrintNames(params IEnumerable<string> names)
{
foreach (var name in names) Console.WriteLine(name);
}
PrintNames("Sahasra", "Priya", "Arjun"); // array
PrintNames(new List<string> { "Sahasra", "Priya" }); // list
// New Lock type - better thread safety
private readonly Lock _lock = new Lock();
using (_lock.EnterScope())
{
// critical section
}
// field keyword in properties - access backing field without declaring it
private string _name = "";
public string Name
{
get => field;
set => field = value.Trim().ToTitleCase(); // field = auto-generated backing field
}
C# 14.0 - 2025 (.NET 10 LTS)
Extensions, field keyword stable, performance improvements
.NET 10 is the next LTS (Long Term Support) release - supported until 2028. C# 14 ships with it in November 2025.
// Extension members (C# 14) - extends types with properties and static methods
// More powerful than extension methods - adds properties too
extension StudentExtensions for Student
{
// Extension property
public string DisplayName => $"{this.Name} ({this.RollNumber})";
// Extension static method
public static Student CreateDefault()
=> new Student { Name = "Unknown", ClassName = "1st" };
}
// Usage
var student = new Student { Name = "Sahasra", RollNumber = "NCA-001" };
Console.WriteLine(student.DisplayName); // Sahasra (NCA-001)
// field keyword - stable in C# 14 (preview in C# 13)
// Access auto-generated backing field in property accessors
public class Student
{
public string Name
{
get => field;
set => field = value?.Trim() ?? string.Empty;
// 'field' replaces need for private _name backing field
}
public double Percentage
{
get => field;
set => field = Math.Clamp(value, 0, 100); // clamp 0-100 automatically
}
}
// Partial properties (C# 14) - split property across partial classes
// Useful for code generators (EF Core, source generators)
public partial class Student
{
public partial string Name { get; set; }
}
public partial class Student
{
private string _nameImpl = "";
public partial string Name
{
get => _nameImpl;
set => _nameImpl = value.Trim();
}
}
.NET 10 - What's New for Backend Developers (2025)
.NET 10 LTS - November 2025
Supported until: November 2028
Key improvements for backend developers:
? ASP.NET Core performance - 20-30% faster HTTP request handling
? EF Core 10 - better LINQ translation, improved raw SQL
? Minimal APIs - improved OpenAPI support built-in
? Native AOT - better compatibility, smaller binaries
? .NET Aspire - production-ready cloud-native orchestration
? AI features - Microsoft.Extensions.AI stable release
? Blazor - improved SSR and streaming improvements
2026 and Beyond - What to Watch
C# direction through 2026:
? AI-first patterns - Microsoft.Extensions.AI, Semantic Kernel integration
? More extension member capabilities
? Performance - Span<T>, Memory<T>, SIMD improvements
? Interoperability - better P/Invoke, COM improvements
? Source generators - more framework code generation
? MAUI - .NET cross-platform mobile improvements
.NET roadmap:
? .NET 10 (Nov 2025) - LTS, use for new projects from 2026
? .NET 11 (Nov 2026) - STS
? .NET 12 (Nov 2027) - LTS
School Management System in 2026
By the time you complete this tutorial series, you will be working with:
Summary - What You Need for This Series
Minimum for Junior Job ? C# 8+ (.NET 6/7/8)
Recommended 2025 ? C# 12 (.NET 10 LTS) or C# 13 (.NET 9)
Next LTS (2025-2026) ? C# 14 (.NET 10 LTS)
Current Latest ? C# 14 preview (.NET 10 RC)
For this tutorial series - install .NET 10 SDK (LTS, supported until Nov 2026).
When .NET 10 releases (Nov 2025), it becomes the recommended version for new projects.
Use ChatGPT, Claude, or Copilot to go deeper on C# version history and features. Try these prompts:
"What are the most important C# features added since C# 5.0 and why do they matter?""Which C# version introduced LINQ and lambda expressions?""What is the difference between records (C# 9) and classes in C#?""What should I know about C# 12 primary constructors if I am learning ASP.NET Core?"
💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.
C# Section Links
Use these links to continue the full Backend > C# topic from the top menu:
Target search terms for this lesson: c# version history, c# 14 features, .net 10 csharp, modern c# features.