Asynchronous programming is essential for building responsive applications, but it comes with challenges - particularly when you need to cancel operations.
Here's how to safely implement cancellation in C#.
The key to proper cancellation is the CancellationTokenSource class. This provides a token that can be passed to async methods and monitored for cancellation requests.
CancellationTokenSource
// Create a cancellation source with timeout var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); var token = cts.Token; try { // Pass token to async operations await DoLongRunningTaskAsync(token); } catch (OperationCanceledException) { // Handle cancellation gracefully Console.WriteLine("Operation was canceled"); } finally { // Always dispose the CancellationTokenSource cts.Dispose(); }
When writing cancellable async methods, check for cancellation at appropriate points:
async Task DoLongRunningTaskAsync(CancellationToken token) { // Check before starting expensive work token.ThrowIfCancellationRequested(); for (int i = 0; i < 100; i++) { // Periodically check during loops if (token.IsCancellationRequested) { // Clean up resources if needed CleanupResources(); // Then throw the standard exception throw new OperationCanceledException(token); } await Task.Delay(100, token); // Built-in methods accept tokens } }
token.ThrowIfCancellationRequested()
OperationCanceledException
By following these patterns, you can ensure your async operations respond promptly to cancellation requests while maintaining clean, resource-efficient code.
In C#, you can format an integer with commas (thousands separator) using ToString with a format specifier.
int number = 1234567; string formattedNumber = number.ToString("N0"); // "1,234,567" Console.WriteLine(formattedNumber);
Explanation:
"N0": The "N" format specifier stands for Number, and "0" means no decimal places. The output depends on the culture settings, so in regions where , is the decimal separator, you might get 1.234.567.
Alternative:
You can also specify culture explicitly if you need a specific format:
using System.Globalization; int number = 1234567; string formattedNumber = number.ToString("N0", CultureInfo.InvariantCulture); Console.WriteLine(formattedNumber); // "1,234,567"
Raw string literals in C# provide a flexible way to work with multiline strings, with some interesting rules around how quotes work.
The key insight is that you can use any number of double quotes (three or more) to delimit your string, as long as the opening and closing sequences have the same number of quotes.
"""
// Three quotes - most common usage string basic = """ This is a basic multiline string """; // Four quotes - when your content has three quotes string withThreeQuotes = """" Here's some text with """quoted""" content """"; // Five quotes - when your content has four quotes string withFourQuotes = """"" Here's text with """"nested"""" quotes """""; // Six quotes - for even more complex scenarios string withFiveQuotes = """""" Look at these """""nested""""" quotes! """""";
The general rule is that if your string content contains N consecutive double quotes, you need to wrap the entire string with at least N+1 quotes. This ensures the compiler can properly distinguish between your content and the string's delimiters.
// Example demonstrating the N+1 rule string example1 = """ No quotes inside """; // 3 quotes is fine string example2 = """" Contains """three quotes""" """"; // Needs 4 quotes (3+1) string example3 = """"" Has """"four quotes"""" """""; // Needs 5 quotes (4+1)
// Indentation example string properlyIndented = """ { "property": "value", "nested": { "deeper": "content" } } """; // This line's position determines the indentation
This flexibility with quote counts makes raw string literals extremely versatile, especially when dealing with content that itself contains quotes, like JSON, XML, or other structured text formats.
Storing passwords as plain text is dangerous. Instead, you should hash them using a strong, slow hashing algorithm like BCrypt, which includes built-in salting and resistance to brute-force attacks.
Step 1: Install BCrypt NuGet Package
Before using BCrypt, install the BCrypt.Net-Next package:
dotnet add package BCrypt.Net-Next
or via NuGet Package Manager:
Install-Package BCrypt.Net-Next
Step 2: Hash a Password
Use BCrypt.HashPassword() to securely hash a password before storing it:
using BCrypt.Net; string password = "mySecurePassword123"; string hashedPassword = BCrypt.HashPassword(password); Console.WriteLine(hashedPassword); // Output: $2a$12$...
Step 3: Verify a Password
To check a user's login attempt, use BCrypt.Verify():
bool isMatch = BCrypt.Verify("mySecurePassword123", hashedPassword); Console.WriteLine(isMatch); // Output: True
Ensuring proper hashing should be at the top of your list when it comes to building authentication systems.
Register for my free weekly newsletter.