Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String interpolation using named parameters in C#6

Given I have a Meta Data resource string stored in my Database that will return like this:

var pageTitle = "Shop the latest {category1} Designer {category2} {category3} at www.abc.com";

And I want to replace the {placeholders} with variable values;

var category1 = "womenswear";
var category2 = "dresses";
var category3 = "cocktail dresses";

I have tried, with no luck;

var newTitle = $"pageTitle, category1, category2, category3";
var newTitle = $(pageTitle, category1, category2, category3);

I know that I could use string.Replace() that has a performance overhead. Does anyone know how this can be done efficiently using the latest C# string interpolation?

like image 841
Lee Swainsbury Avatar asked Apr 20 '16 13:04

Lee Swainsbury


People also ask

What is string interpolation in C?

String interpolation is a technique that enables you to insert expression values into literal strings. It is also known as variable substitution, variable interpolation, or variable expansion. It is a process of evaluating string literals containing one or more placeholders that get replaced by corresponding values.

What is string interpolation example?

WriteLine("Hello, {0}! Today is {1}, it's {2:HH:mm} now.", name, date. DayOfWeek, date); // String interpolation: Console. WriteLine($"Hello, {name}!

What is the correct syntax for string interpolation?

Syntax of string interpolation starts with a '$' symbol and expressions are defined within a bracket {} using the following syntax. Where: interpolatedExpression - The expression that produces a result to be formatted.

How do you add parameters to a string?

In expressions, place quotes around the parameter reference ${param-name} when you want that parameter's value to be resolved as a string. For example: To use the value of <operator-parameter name="starter" value="hundred"/> as a string in an expression, reference the parameter as: "${starter}" .


3 Answers

You can't use string interpolation here. String interpolation is a compile-time rewrite method for string.Format, which is the solution you should use:

var newTitle = string.Format("{0}, {1}, {2}, {3}", pageTitle, category1, category2, category3);

Or string.Join:

var newTitle - string.Join(", ", new string[] { pageTitle, category1, category2, category3 });

Since you are loading from database, it might be just better in your case to keep using string.Replace.

like image 146
Patrick Hofman Avatar answered Oct 21 '22 01:10

Patrick Hofman


I know that I could use string.Replace() that has a performance overhead

Of mere nanoseconds. You shouldn't optimize prematurely.

As said, the C# 6 string interpolation feature happens at compile-time. If you want to do this at runtime, you'll have to use string replacement.

I assume your strings are formatted like that for ease of editing and not having a fixed replacement order, so simply do this:

var input = "Shop the latest {category1} Designer {category2} {category3} at www.abc.com";
var category1 = "womenswear";
var category2 = "dresses";
var category3 = "cocktail dresses";

var result = input.Replace("{category1}", category1)
                  .Replace("{category2}", category2)
                  .Replace("{category3}", category3);

This will just work. You could also store your replacement values in a dictionary, and loop over the keys to replace the key with the value.

like image 25
CodeCaster Avatar answered Oct 21 '22 01:10

CodeCaster


Although .NET does not offer a built-in capability for this, you can easily build a pretty good implementation with regex:

public static string Format(string formatWithNames, IDictionary<string,object> data) {
    int pos = 0;
    var args = new List<object>();
    var fmt = Regex.Replace(
        formatWithNames
    ,   @"(?<={)[^}]+(?=})"
    ,   new MatchEvaluator(m => {
            var res = (pos++).ToString();
            var tok = m.Groups[0].Value.Split(':');
            args.Add(data[tok[0]]);
            return tok.Length == 2 ? res+":"+tok[1] : res;
        })
    );
    return string.Format(fmt, args.ToArray());
}

The idea is to replace names with consecutive numbers (see sb.Append(pos++)), build an array of object parameters (see args.Add(data[tok[0]])), and pass the result to string.Format to use string's formatting capabilities.

Now you can pass your resource to this Format, along with a dictionary of key-value pairs, and get a string formatted using .NET's built-in formatting capabilities:

var x = new Dictionary<string,object> {
    {"brown", 1}
,   {"jumps", 21}
,   {"lazy", 42}
};
Console.WriteLine("{0}", Format("Quick {brown} fox {jumps:C} over the {lazy:P} dog", x));

Note that there is no $ in front of the string literal, so there's no C#'s built-in interpolation going on here.

This prints

Quick 1 fox $21.00 over the 4,200.00 % dog

The approach is based on the idea by Scott Hanselman, except formatting is done differently.

Demo.

like image 28
Sergey Kalinichenko Avatar answered Oct 21 '22 02:10

Sergey Kalinichenko