
Did you know that if you're working with .NET Framework versions 4.7.2 up to 4.8.1 alongside Visual Studio 2022, you can upgrade to C# 12? By adding a few components via NuGet and changing the LangVersion key in your .csproj files to <LangVersion>12.0</LangVersion>, you're set for the shift.
For ASP.NET WebForms projects, a slight tweak in your Web.Config is needed to sync with Roslyn.
This shift brings a significant edge, keeping you and your team on the cutting edge with C# 12's latest features.
In this article, I'll showcase how C# 12 will enhance your programming capabilities. And for deployment? The process remains seamless using GitHub Actions or any other CI/CD platform.
Stay tuned to discover the transformative power of C# 12!
Let's do it!
Starting adding the last version of these packages from NuGet to your CS projects:

Upgrading from C# 7.3 to C# 12 brings many new features and changes that vastly increase the language's capabilities and development experience.
Modify your .csproj files by adding the LangVersion key like this.
<PropertyGroup>
<LangVersion>12.0</LangVersion>
What can you do now in C# 12?
Here's a rundown of the significant changes and additions between C# 7.3 and C# 12.
Literals
Literals are easy to declare.
var dataId = 1;
// C# 7.3
var text73 = $@"
{{data}}:{dataId}
";
var json73 = @"
{{
""name"": ""John"",
""age"": 30
}}
";
// C# 12
var text12 = $$"""
{data}:{{dataId}}
""";
var json12 = """
{
"name": "John",
"age": 30
}
""";
Return default value
Sample 1. Returning array values with [].
// C# 7.3
private List<string> Values73(bool retEmpty = true)
{
if (retEmpty) return new List<string>();
return new List<string> { "Test1", "Test2" };
}
// C# 12
private List<string> Values(bool retEmpty = true)
{
if (retEmpty) return [];
return ["Test1", "Test2"];
}
Sample 2. Returning empty array.
// C# 7.3
private List<string> Parameters73()
{
return new List<string>();
}
// C# 12.0
private List<string> Parameters()
{
return [];
}
Property and Tuple Pattern
Tuples efficiently pass parameters and serve as return values.
// C# 7.3
private string PointTuple73()
{
var pointX = 3; var pointY = 4;
if (pointX == 3 && pointY == 4) return "Origin";
if (pointX == pointY) return "On the diagonal";
return "Other point";
}
// C# 12
private string PointTuple12()
{
var point = (x: 3, y: 4);
var result = point switch
{
(0, 0) => "Origin",
var (x, y) when x == y => "On the diagonal",
_ => "Other point"
};
return result;
}
Switch expressions
The switch is more direct.
// C# 7.3
private string Direction73()
{
var direction = DefaultLocal73();
switch (direction)
{
case "north":
return "move up";
case "south":
return "move down";
default:
return "undefined";
}
}
// C# 12
private string Direction12()
{
var direction = DefaultLocal();
var movement = direction switch
{
"north" => "move up",
"south" => "move down",
_ => "undefined"
};
return movement;
// Local function
static string DefaultLocal() => "north";
}
Switch expression with type
Now, you can check the type of the objects.
// C# 7.3
private string Result73(object value)
{
if (value.GetType() == typeof(string)) return "String";
if (value.GetType() == typeof(int)) return "Int number";
return "Another type";
}
// C# 12
private string Result12(object value)
{
var resultado = value switch
{
int i => "Int number",
string s => "String",
_ => "Another type"
};
return resultado;
}
Nullable
To use Nullables, declare them at the top of the file .cs with #nullable enabled.

Join the conversation! Your thoughts help the community grow.