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.