C# 1.0 |
2002 |
Basic language syntax, classes, interfaces, inheritance |
|
C# 2.0 |
2005 |
Generics, anonymous methods, nullable types, iterators |
// Usage of GenericList
GenericList intList = new GenericList();
// Anonymous methods
PrintDelegate print = delegate(string msg)
{
Console.WriteLine(msg);
};
// Nullable types
int? nullableInt = null;
if (nullableInt.HasValue)
{
Console.WriteLine(nullableInt.Value);
}
// Iterators
public IEnumerator GetEnumerator()
{
yield return 1;
yield return 2;
yield return 3;
|
C# 3.0 |
2007 |
LINQ (Language Integrated Query), lambda expressions, implicit typing (var) |
// LINQ (Language Integrated Query)
List numbers = new List { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(n => n % 2 == 0);
// Lambda expressions
Func add = (a, b) => a + b;
// Implicit typing (var)
var message = "Hello, C# 3.0!";
|
C# 4.0 |
2010 |
Optional parameters, named arguments, dynamic binding |
// Optional parameters
public void Display(string message = "Hello")
{
Console.WriteLine(message);
}
// Named arguments
Display(message: "Hi");
// Dynamic binding
dynamic dyn = 10;
Console.WriteLine(dyn.GetType()); // Outputs System.Int32
|
C# 5.0 |
2012 |
Asynchronous methods (async/await) |
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task Main()
{
await DoAsync();
}
static async Task DoAsync()
{
await Task.Delay(1000);
Console.WriteLine("Async method executed.");
}
}
|
C# 6.0 |
2015 |
Expression-bodied members, null-conditional operators |
// Expression-bodied members
public string GetName() => "Anu Ray";
// Null-conditional operator
string name = null;
Console.WriteLine(name?.Length); // Outputs null instead of throwing NullReferenceException
|
C# 7.0 |
2017 |
Tuples, pattern matching, out variables |
// Tuples
var person = (Name: "Anu", Age: 30);
Console.WriteLine($"{person.Name} is {person.Age} years old.");
// Pattern matching
object obj = "Hello";
if (obj is string str)
{
Console.WriteLine($"Length of string is {str.Length}");
}
// Out variables
if (int.TryParse("123", out int number))
{
Console.WriteLine($"Parsed number: {number}");
}
|
C# 7.1 |
2017 |
Async main method, default literal |
// Async main method
public static async Task Main()
{
await DoAsync();
}
static async Task DoAsync()
{
await Task.Delay(1000);
Console.WriteLine("Async main method executed.");
}
// Default literal
public void Display(int value = default)
{
Console.WriteLine(value);
}
|
C# 7.2 |
2017 |
Ref readonly locals and returns, non-trailing named arguments |
// Ref readonly locals and returns
int[] array = { 1, 2, 3 };
ref readonly int second = ref GetSecond(array);
Console.WriteLine(second);
static ref readonly int GetSecond(int[] arr)
{
return ref arr[1];
}
// Non-trailing named arguments
Display(message: "Hello", count: 5);
static void Display(string message, int count)
{
for (int i = 0; i < count; i++)
{
Console.WriteLine(message);
}
}
|
C# 7.3 |
2018 |
Enum enhancements, tuple equality |
// Enum enhancements
public enum Season
{
Spring = 1,
Summer = 2,
Autumn = 3,
Winter = 4
}
// Tuple equality
var tuple1 = (Name: "Anu", Age: 30);
var tuple2 = (Name: "Anu", Age: 30);
Console.WriteLine(tuple1 == tuple2); // Outputs true
|
C# 8.0 |
2019 |
Nullable reference types, asynchronous streams, switch expressions |
// Nullable reference types
#nullable enable
string? name = null;
Console.WriteLine(name.Length); // Compiler warning for potential null reference
// Asynchronous streams
await foreach (var item in GetNumbersAsync())
{
Console.WriteLine(item);
}
static async IAsyncEnumerable GetNumbersAsync()
{
for (int i = 1; i <= 5; i++)
{
await Task.Delay(100);
yield return i;
}
}
// Switch expressions
int number = 5;
string result = number switch
{
1 => "One",
2 => "Two",
_ => "Other"
};
Console.WriteLine(result);
|
C# 9.0 |
2020 |
Records, init-only properties, pattern matching enhancements |
// Records
public record Person(string FirstName, string LastName);
var person = new Person("Anu", "Ray");
var updatedPerson = person with { LastName = "Smith" };
Console.WriteLine($"Original: {person.FirstName} {person.LastName}");
Console.WriteLine($"Updated: {updatedPerson.FirstName} {updatedPerson.LastName}");
// Init-only properties
public class Point
{
public int X { get; init; }
public int Y { get; init; }
}
var point = new Point { X = 10, Y = 20 };
// point.X = 30; // Error: Cannot modify init-only property
// Pattern matching enhancements
object obj = "Hello";
if (obj is string { Length: > 5 } str)
{
Console.WriteLine($"String '{str}' has length greater than 5.");
}
|
C# 10.0 |
2021 |
File-scoped namespaces, global using directives, interpolated strings with `@$` |
// File-scoped namespaces
namespace MyNamespace;
public class MyClass
{
public void Display()
{
Console.WriteLine("Hello from MyClass.");
}
}
// Global using directives
global using System;
var date = DateTime.Now;
Console.WriteLine($"Current date and time: {date}");
// Interpolated strings with @$
string name = "Anu";
string message = @$"Hello {name},
Welcome to our application!";
Console.WriteLine(message);
|
C# 11.0 |
2022 |
Raw string literals,Generic attributes,Newlines in string interpolation expressions,
List patterns,File-local types,Required members,Auto-default structs |
// C# 11 feature:
//define like this
public class GenericAttribute : Attribute { }
//Use
[GenericAttribute()]
public string Method() => default;
//The text inside the { and } characters for a string interpolation
// can now span multiple lines.A raw string literal starts with at least three
// double-quote (""") characters
string longMessage = """
This is a long message.
It has several lines.""";
//List patterns Beginning with C# 11, you can match an array or a list
//against a sequence of patterns, as the following
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers is [1, 2, 3]); // True
|