C# is a programming language developed by Microsoft for building Windows and web applications. Here is a brief overview of the features added in each version of C#, starting with the first version:
C# 1.0 (2002):
- Basic language constructs such as classes, interfaces, and structs
class Example
{
public int Add(int a, int b)
{
return a + b;
}
}
- Support for delegates and events
- Support for properties and indexers
- Support for exceptions and try-catch-finally blocks
C# 2.0 (2005):
- Introduction of Generics
class Example<T>
{
public T Add(T a, T b)
{
return a + b;
}
}
- Support for anonymous methods
- Introduction of nullable types
- Introduction of the “yield” keyword for creating iterator methods
C# 3.0 (2007):
- Introduction of the “var” keyword for implicit typing
var myList = new List<int> { 1, 2, 3 };
- Support for extension methods
- Support for lambda expressions
List<int> myList = new List<int> { 1, 2, 3 };
myList.Where(x => x > 1);
- Support for expression trees
- Introduction of Language Integrated Query (LINQ)
var query = from i in myList where i > 1 select i;
C# 4.0 (2010):
- Support for dynamic binding
dynamic example = new Example();
example.Add(1, 2);
- Support for named and optional arguments
- Support for generic covariance and contravariance
C# 5.0 (2012):
- Introduction of the “async” and “await” keywords for asynchronous programming
async Task<int> Example()
{
return await Task.FromResult(1);
}
C# 6.0 (2015)
- Introduction of the “using static” keyword to import and use static members from a type without specifying the type name
using static System.Console;
WriteLine("Hello World");
- Support for auto-property initializers
class Example
{
public int X { get; } = 5;
}
- Support for expression-bodied members
class Example
{
public int Add(int a, int b) => a + b;
}
C# 7.0 (2017)
- Support for tuples and tuple matching
Copy code(int x, int y) Example()
{
return (1, 2);
}
- Support for pattern matching
Example example = new Example();
switch (example)
{
case Example e when e.Add(1, 2) > 0:
break;
}
- Support for ref locals and returns
- Support for local functions
C# 8.0 (2019)
- Introduction of null-coalescing assignment
int? x = null;
int y = x ?? 0;
- Support for asynchronous streams
using System.Threading.Tasks;
class Example
{
public async IAsyncEnumerable<int> GetData()
{
await Task.Delay(1000);
yield return 1;
await Task.Delay(1000);
yield return 2;
}
}
- Support for default interface methods
interface Example
{
int Add(int a, int b) => a + b;
}
- Support for ranges and indices
string example = "Hello World";
var substring = example[1..5];
C# 9.0 (2020)
- Introduction of records, structs with more functionality
record Example
{
public int Add(int a, int b) => a + b;
}
- Introduction of top-level programs
class Program
{
public static void Main()
{
Console.WriteLine("Hello World!");
}
}
- Introduction of init-only properties
class Example
{
public int X { get; init; }
}
- Introduction of target-typed new expressions
var example = new Example { X = 1 };
C# 10.0 (2021)
- Introduction of “Recursive patterns”
Example example = new Example();
switch (example)
{
case Example e when e.Add(1, 2) > 0:
break;
case Example e:
e.Add(1, 2);
break;
}
- Introduction of “patterns in field declarations”
class Example
{
public int X { get; set; }
public int Y { get; set; }
public int Add(int a, int b) => a + b;
}
Example example = new Example();
switch (example)
{
case Example { X: 1, Y: 2 }:
break;
}
- Introduction of “patterns in property declarations”
class Example
{
public int X { get; set; }
public int Y { get; set; }
public int Add(int a, int b) => a + b;
}
Example example = new Example();
switch (example)
{
case Example { X: var x, Y: var y }:
break;
}
C# 11.0 (2022)
- Introduction of “source generators”
class Example
{
public int Add(int a, int b) => a + b;
}
- Introduction of “concurrent and parallel” programming features
class Example
{
public void DoWork()
{
Parallel.ForEach(1, 10, i =>
{
// Do work
});
}
}
C# 12.0 (2022)
- Introduction of “Switch expression”
Example example = new Example();
var result = example switch
{
{ Add: 1 } => "One",
{ Add: 2 } => "Two",
_ => "Other"
};
- Introduction of “Recursive patterns”
Example example = new Example();
switch (example)
{
case Example e when e.Add(1, 2) > 0:
break;
case Example e:
e.Add(1, 2);
break;
}
- Introduction of “patterns in function pointers”
class Example
{
public int Add(int a, int b) => a + b;
}
Example example = new Example();
switch (example.Add)
{
case 0:
break;
case int x when x > 0:
break;
}
C# 13.0 (2023)
- Introduction of “null-conditional dereference”
Example example = new Example();
var result = example?.Add(1, 2);
- Introduction of “target-typed default literals”
var example = new Example { X = default };
- Introduction of “extended target-typed new expressions”
var example = new Example { X = 1 } with { Y = 2 };
C# 14.0 (2023)
- Introduction of “null-coalescing assignment with pattern matching”
int? x = null;
int y = x switch
{
int i when i > 0 => i,
_ => 0
};
- Introduction of “pattern matching with logical and/or”
Example example = new Example();
switch (example)
{
case Example { X: int x } when x > 0 || x < 0:
break;
}
- Introduction of “matching on type”
object example = new Example();
switch (example)
{
case Example e:
break;
}
These are just some basic examples of the features added in each version of C#. The actual usage of these features could be much more complex, depending on the specific use case.