CodeOn.NET

Code, Learn, Build in .NET
Theme:
    December 13, 2025 7 min read

    String Templating in .NET: From basics to Scriban

    String templating is essential in C# like other programming languages. It is the process of embedding data (like variables or objects) directly into a text structure or template to produce a final string.

    C# has several ways to achieve this, from simple string concatenation to String.Format, and modern string interpolation.

    But sometimes you need more power: you need to handle complex logic, loops, or conditionals inside your templates. The built-in C# APIs don't support these features.

    That's where third-party libraries help. Scriban is a powerful templating engine for .NET. This post will look at string templating in C#. We'll cover the basic C# methods, and then we'll see why and how to use a more robust library like Scriban.

    1. String Concatenation


    This is the simplest way. You use the plus sign (+) to join strings together. It works, but it's not the best approach.

    If you have a lot of variables, the code gets hard to read. Plus, it creates many new string objects. This can slow things down if you are building strings in a tight loop. We don't use this much anymore for complex strings. There are better, cleaner options.

    string name = "Jon";
    int age = 30;
    string message = "Hello, my name is " + name + " and I am " + age + " years old.";
    // "Hello, my name is Jon and I am 30 years old."

    2. String.Format


    The next step up is the static method String.Format. This has been a standard in .NET for a long time. It uses numbered placeholders like {0} and {1} inside the string. You pass the variables separately to fill those spots.

    This approach is cleaner than using the + operator and supports basic formatting like currency {0:C}.

    string name = "Jon";
    int age = 30;
    // {0} is 'name', {1} is 'age'.
    string message = String.Format("Hello, my name is {0} and I am {1} years old.", name, age);
    // "Hello, my name is Jon and I am 30 years old."

    3. String Interpolation


    Interpolation is the modern standard for C# strings. You start the string with a dollar sign ($). Put the variable names directly inside {}.

    It's much cleaner than String.Format. You don't use numbered placeholders. The code is easy to read because it looks like the final output.

    It still handles formatting, like turning a number into currency ":C"

    string name = "Jon";
    int age = 30;
    // Note the $ before the quotes.
    string message = $"Hello, my name is {name} and I am {age} years old.";
    // "Hello, my name is Jon and I am 30 years old."

    4. StringBuilder


    When you need to build a string out of many pieces, especially inside a loop, using + or string interpolation can hurt performance. Every time you join two strings, the system creates a brand new string object in memory.

    The StringBuilder class fixes this. Instead of creating new strings, it uses an internal buffer (an array of characters) to hold and modify the text.

    string name = "Jon";
    int age = 30;

    var builder = new StringBuilder("Hello, my name is "); builder.Append(name);
    builder.Append(" and I am ");
    builder.Append(age);
    builder.Append(" years old.");

    string message = builder.ToString();
    // "Hello, my name is Jon and I am 30 years old."

    5. FormattableString / IFormattable


    This is how string interpolation works at a lower level. If you assign an interpolated expression to a FormattableString variable, the string is not created yet.

    The object holds the format string and the data arguments separately. This is useful for things like logging or internationalization. You can capture the format and the data separately. You get the raw data and the template.

    string name = "Jon";

    FormattableString fs = $"Hello, my name is {name} and I am {30} years old.";

    // The final string is NOT created yet.
    Console.WriteLine(fs.Format); // Output: Hello, my name is {0} and I am {1} years old.
    Console.WriteLine(fs.GetArguments()[0]); // Output: Jon

    6. DefaultInterpolatedStringHandler


    This is an advanced feature added in C# 10 for better performance. You don't use it directly, it runs automatically behind your string interpolation.

    What it does is make interpolation faster. It avoids creating the temporary object[] arrays used by older methods. It also uses stack memory when possible, which reduces garbage collection work.

    This is just an optimization. It gives you the clean, readable syntax of string interpolation with performance almost as good as StringBuilder for single uses.

    The code shown is compiler generated from the string interpolation syntax.

    string message = $"Hello, my name is {name} and I am {age} years old";

    // compiler generated code for the message varaible!

    string value = "Jon";
    int value2 = 30;
    DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(39, 2);
    defaultInterpolatedStringHandler.AppendLiteral("Hello, my name is ");
    defaultInterpolatedStringHandler.AppendFormatted(value);
    defaultInterpolatedStringHandler.AppendLiteral(" and I am ");
    defaultInterpolatedStringHandler.AppendFormatted(value2);
    defaultInterpolatedStringHandler.AppendLiteral(" years old.");
    string text = defaultInterpolatedStringHandler.ToStringAndClear();

    7. Other Templating Engines


    Sometimes simple formatting isn't enough. When you need to render things like complex HTML emails or documents, you need a full templating engine. These libraries completely separate the template (the design) from the data (the content).

    These libraries are powerful because they let you put logic like for loops and if/else statements directly into the template file. Engines include: Scriban (fast, Liquid-like), RazorLight (uses Razor syntax), Liquid (very safe), and Handlebars.Net. They are overkill for logging, but essential for serious document generation.

    Scriban: The Next Step in .NET Templating


    Scriban is popular because it's Fast, Lightweight, and Safe. Its language is also close to Liquid. It handles that complex logic cleanly.

    How Scriban Works

    1. Parse: You call Template.Parse() on your template text. This prepares it to run fast.

    2. Render: You call .Render() and pass in your C# data (the model). Scriban runs the logic and outputs the final string.

    Scriban uses named fields instead of numbers. This makes managing large templates much easier.

    var templateStr = @"{{ code }} is your {{ module }} verification code.";

    C# Code to Render It:

    var template = Template.Parse(templateStr);

    // Render it with an anonymous object as the model
    var res = template.Render(new { code = "1234", module = "Login" }); // Output is "1234 is your Login verification code."

    This example shows loops and conditionals in Scriban using nested objects

    var templateData = new
    {
    Categories = categories,
    Paginator = new
    {
    PrevPageUrl = prev == null ? null : (prev == 1 ? "index.html" : "page-1.html")
    }
    };

    Scriban template syntax with HTML markup

    {{ for category in categories }}
        <a href="{{ category.slug }}">{{ category.name }}</a>
    {{ end }}
    
    {{ if paginator.prev_page_url }}
      <a href="{{ paginator.prev_page_url }}">Newer</a>
    {{ end }}

    Conclusion

    String templating in C# has a lot of options. Which one you use just depends on the complexity of the job.

    For quick, simple, and readable string creation, string interpolation is the clear winner and the modern standard.

    If you're joining a very large number of strings in a loop where performance is critical, you should use StringBuilder.

    But once your templates need logic like if statements or loops you need to move beyond the built-in C# features. That's where powerful third-party engines come in.

    Choosing the right tool is key. It keeps your C# code clean and your templates easy to manage.

    You can find the libraries here:

    1. Scriban - https://github.com/scriban/scriban
    2. RazorLight - https://github.com/toddams/RazorLight
    3. Handlebars.Net - https://github.com/Handlebars-Net/Handlebars.Net
    4. DotLiquid - https://github.com/dotliquid/dotliquid
    Category
    C#
    Tags
    Share