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
73

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
122

Reading a file line by line is useful when handling large files without loading everything into memory at once.

✅ Best Practice: Use File.ReadLines() which is more memory efficient.

Example

foreach (string line in File.ReadLines("file.txt"))
{
    Console.WriteLine(line);
}

Why use ReadLines()?

Reads one line at a time, reducing overall memory usage. Ideal for large files (e.g., logs, CSVs).

Alternative: Use StreamReader (More Control)

For scenarios where you need custom processing while reading the contents of the file:

using (StreamReader reader = new StreamReader("file.txt"))
{
    string? line;
    while ((line = reader.ReadLine()) != null)
    {
        Console.WriteLine(line);
    }
}

Why use StreamReader?

Lets you handle exceptions, encoding, and buffering. Supports custom processing (e.g., search for a keyword while reading).

When to Use ReadAllLines()? If you need all lines at once, use:

string[] lines = File.ReadAllLines("file.txt");

Caution: Loads the entire file into memory—avoid for large files!

3
264

When working with SQL Server, you may encounter scenarios where you need to combine multiple row values into a single column. Prior to SQL Server 2017, this required using STUFF() with FOR XML PATH(), but now, the STRING_AGG() function provides a simpler approach.

What is STRING_AGG()?

The STRING_AGG() function concatenates values from multiple rows into a single string with a specified separator.

Basic Syntax:

SELECT STRING_AGG(column_name, ', ') AS concatenated_values
FROM table_name;
  • column_name: The column whose values you want to concatenate.
  • ', ': The separator used between values.

Example Usage

Consider a Customers table:

id name
1 Alice
2 Bob
3 Charlie

Using STRING_AGG(), we can concatenate the names:

SELECT STRING_AGG(name, ', ') AS customer_names
FROM Customers;

Result:

Alice, Bob, Charlie

Using STRING_AGG() with GROUP BY

You can also use STRING_AGG() within GROUP BY to aggregate data by a specific column. Consider an Orders table:

customer_id product
1 Laptop
1 Mouse
2 Keyboard
2 Monitor

To get a list of products purchased by each customer:

SELECT customer_id, STRING_AGG(product, ', ') AS purchased_products
FROM Orders
GROUP BY customer_id;

Result:

customer_id | purchased_products
------------|-------------------
1           | Laptop, Mouse
2           | Keyboard, Monitor

Sorting Values in STRING_AGG()

By default, STRING_AGG() does not guarantee an order. To enforce ordering, use WITHIN GROUP (ORDER BY column_name). Example:

SELECT STRING_AGG(name, ', ') WITHIN GROUP (ORDER BY name) AS sorted_names
FROM Customers;

Key Benefits of STRING_AGG():

  • Eliminates complex workarounds like STUFF() with FOR XML PATH().
  • More readable and concise syntax.
  • Works efficiently with GROUP BY for aggregating related data.

STRING_AGG() is a powerful function that simplifies string concatenation in SQL Server, making queries cleaner and more efficient. Happy querying!

0
83