Unlocking the Power of CSharp: 15 Lesser-Known Features Every Developer Should Master

C# tool box
Why did the C# developer bring a ladder to the coding session?

Because they heard there were some "high-level" features they hadn't discovered yet!

C# is a rich and powerful language with many lesser-known features that can be highly beneficial. Here are some lesser-known functions, keywords, and classes worth exploring:

1. Tuples

Tuples provide a way to group multiple values into a single object. They are useful for returning multiple values from a method.

public (int, string) GetPersonData()
{
    return (1, "John Doe");
}

2. Deconstruction

Deconstruction allows for easy unpacking of tuples and other objects.

(int id, string name) = GetPersonData();

3. Local Functions

Local functions are functions declared inside another function. They can help with organizing code and maintaining scope.

void MainFunction()
{
    void LocalFunction()
    {
        Console.WriteLine("This is a local function.");
    }

    LocalFunction();
}

4. Pattern Matching

Pattern matching can be used to simplify code that involves checking types or values.

object obj = "hello";
if (obj is string s)
{
    Console.WriteLine(s.ToUpper());
}

5. Using Static

The using static directive allows you to import static members of a class, making the code more concise.

using static System.Math;
Console.WriteLine(Sqrt(4));

6. Ref Locals and Returns

Ref locals and returns allow for the modification of variables directly.

ref int FindNumber(int[] numbers, int target)
{
    for (int i = 0; i < numbers.Length; i++)
    {
        if (numbers[i] == target)
            return ref numbers[i];
    }
    throw new IndexOutOfRangeException();
}

int[] nums = { 1, 2, 3 };
ref int num = ref FindNumber(nums, 2);
num = 42;
Console.WriteLine(nums[1]); // Outputs 42

7. Default Interface Methods

C# 8.0 introduced default implementations for interface methods, providing a way to add new methods to interfaces without breaking existing implementations.

public interface IMyInterface
{
    void Method1();

    void Method2()
    {
        Console.WriteLine("Default implementation of Method2");
    }
}

8. Span and Memory

These are used for high-performance memory management and manipulation.

Span<int> numbers = stackalloc int[10];
numbers[0] = 42;
Console.WriteLine(numbers[0]);

9. The using Declaration

Introduced in C# 8.0, the using declaration simplifies the syntax for IDisposable objects.

using var resource = new Resource();
resource.DoSomething();

10. Nullable Reference Types

C# 8.0 introduced nullable reference types to help prevent null reference exceptions.

#nullable enable
string? possiblyNull = null;

11. Caller Information Attributes

These attributes provide information about the caller of a method, useful for debugging and logging.

public void Log(string message,
    [CallerMemberName] string memberName = "",
    [CallerFilePath] string filePath = "",
    [CallerLineNumber] int lineNumber = 0)
{
    Console.WriteLine($"[{memberName}] {message}");
}

12. Record Types

Records are a reference type that provides built-in functionality for encapsulating data.

public record Person(string FirstName, string LastName);

13. Async Streams

Async streams allow for asynchronous iteration over IAsyncEnumerable.

public async IAsyncEnumerable<int> GetNumbersAsync()
{
    for (int i = 0; i < 10; i++)
    {
        await Task.Delay(1000);
        yield return i;
    }
}

await foreach (var number in GetNumbersAsync())
{
    Console.WriteLine(number);
}

14. Index and Range

These features provide a simpler syntax for working with ranges and indices.

int[] array = { 1, 2, 3, 4, 5 };
int last = array[^1]; // 5
int[] subArray = array[1..3]; // { 2, 3 }

15. System.Text.Json

A high-performance JSON library that is part of .NET Core.

using System.Text.Json;

var jsonString = JsonSerializer.Serialize(new { Name = "John", Age = 30 });
var person = JsonSerializer.Deserialize<Person>(jsonString);

Exploring these features can greatly enhance your productivity and capabilities as a C# developer. Many of these are introduced in the more recent versions of C#, so ensure your development environment is up-to-date to leverage these functionalities.