C# Language Features

Explore the powerful and evolving features of the C# programming language, designed to enhance productivity, readability, and performance for .NET developers.

Introduction

C# is a modern, object-oriented, and type-safe programming language developed by Microsoft. It's a versatile language that can be used for a wide range of applications, from web services and desktop applications to mobile apps and cloud services.

This article provides an overview of key C# language features that have been introduced over various versions, highlighting their benefits and how they can be leveraged in your projects.

Key Features

1. Async/Await

Simplify asynchronous programming with the async and await keywords. This feature allows you to write non-blocking code that appears synchronous, greatly improving responsiveness in applications, especially for I/O-bound operations.


async Task<string> GetDataAsync(string url)
{
    using (HttpClient client = new HttpClient())
    {
        string result = await client.GetStringAsync(url);
        return result;
    }
}
                    

2. LINQ (Language Integrated Query)

LINQ provides a powerful and consistent way to query data from various sources, such as collections, databases, and XML documents, directly within the C# language. It enhances code readability and reduces boilerplate code.


var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var evenNumbers = numbers.Where(n => n % 2 == 0);

foreach (var num in evenNumbers)
{
    Console.WriteLine(num);
}
                    

3. Pattern Matching

Pattern matching allows you to check if an expression has a certain structure and, if so, extract data from it. This feature has evolved significantly, offering concise ways to handle complex conditional logic.


public string Classify(object shape)
{
    return shape switch
    {
        Rectangle r => $"Rectangle with area {r.Width * r.Height}",
        Circle c => $"Circle with area {Math.PI * c.Radius * c.Radius}",
        _ => "Unknown shape"
    };
}
                    

4. Nullable Reference Types

Nullable reference types help prevent null reference exceptions by allowing you to specify whether a reference type can be null. This significantly improves code safety and reduces runtime errors.


string name = "Alice"; // Non-nullable by default
string? nullableName = null; // Explicitly nullable

// Compiler warns if you try to dereference a nullable type without checking
// Console.WriteLine(nullableName.Length); // Potential warning
                    

5. Records

Records are a special kind of class that provides concise syntax for creating immutable data types. They are ideal for representing data where immutability and value-based equality are important.


public record Person(string FirstName, string LastName);

var person1 = new Person("Jane", "Doe");
var person2 = new Person("Jane", "Doe");

Console.WriteLine(person1 == person2); // Output: True (value-based equality)
                    

6. Global Using Directives

For projects with many files that use the same set of using directives, C# 10 allows you to declare them globally, reducing redundancy and improving file cleanliness.


// In a GlobalUsings.cs file
global using System;
global using System.Collections.Generic;
global using System.Linq;
                    

7. File-Scoped Namespaces

C# 10 also introduces file-scoped namespaces, allowing you to declare a namespace for an entire file, further simplifying code structure and reducing braces.


namespace MyProject.Utilities; // File-scoped namespace

public class Helper
{
    // ...
}
                    

Further Resources