Menu

How do Raw String Literals Work in C#

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.

The Basic Rules

  1. You must use at least three double quotes (""") to start and end a raw string literal
  2. The opening and closing quotes must have the same count
  3. The closing quotes must be on their own line for proper indentation
  4. If your string content contains a sequence of double quotes, you need to use more quotes in your delimiter than the longest sequence in your content

Examples with Different Quote Counts

// 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 N+1 Rule

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)

Practical Tips

  • Start with three quotes (""") as your default
  • Only increase the quote count when you actually need to embed quote sequences in your content
  • The closing quotes must be on their own line and should line up with the indentation you want
  • Any whitespace to the left of the closing quotes defines the baseline indentation
// 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.

1
69

Related

File-scoped namespaces, introduced in C# 10, provide a more concise way to declare namespaces in your code files.

This feature helps reduce nesting levels and makes your code cleaner and more readable. Let's explore how to use them effectively and understand their benefits.

Traditional Namespace Declaration

Traditionally, C# developers have used block-scoped namespaces, which require curly braces and add an extra level of indentation:

namespace MyCompany.MyProduct.Features
{
    public class UserService
    {
        private readonly string _connectionString;

        public UserService(string connectionString)
        {
            _connectionString = connectionString;
        }

        public void CreateUser(string username)
        {
            // Implementation
        }
    }

    public record User(string Username, string Email);
}

Modern File-Scoped Namespace

With file-scoped namespaces, you can declare the namespace without braces, reducing indentation and making the code more readable:

namespace MyCompany.MyProduct.Features;

public class UserService
{
    private readonly string _connectionString;

    public UserService(string connectionString)
    {
        _connectionString = connectionString;
    }

    public void CreateUser(string username)
    {
        // Implementation
    }
}

public record User(string Username, string Email);

Key Benefits and Best Practices

  1. Reduced Indentation: File-scoped namespaces eliminate one level of indentation, making the code easier to read and maintain.

  2. Single Namespace per File: File-scoped namespaces enforce a good practice of having only one namespace per file, improving code organization.

  3. Compatibility: File-scoped namespaces work seamlessly with existing code and can be gradually adopted in your codebase.

Important Considerations

When using file-scoped namespaces, keep these points in mind:

  • You can only have one namespace declaration per file
  • The namespace declaration must be the first non-comment line in the file
  • You cannot mix traditional and file-scoped namespace declarations in the same file

Migration Tips

When converting existing code to use file-scoped namespaces:

  1. Start with new files, using file-scoped namespaces from the beginning
  2. Gradually convert existing files during regular maintenance work
  3. Use IDE tools to automate the conversion process
  4. Ensure your team agrees on the migration approach and timeline

Conclusion

File-scoped namespaces are a simple yet effective feature that can make your C# code more readable and maintainable. While the benefits might seem small, they add up significantly in larger codebases. Consider adopting this modern syntax in your C# projects, especially if you're using C# 10 or later.

0
90

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"
3
168

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.

2
217