Named String Formatting in C#

Is there a String.Format that can accept named input parameters instead of index placeholders?

In C# 6 you can use string interpolation:

string name = "Lisa";
int age = 20;
string str = $"Her name is {name} and she's {age} years old";

As Doug Clutter mentioned in his comment, string interpolation also supports format string. It's possible to change the format by specifying it after a colon. The following example will output a number with a comma and 2 decimal places:

var str = $"Your account balance is {balance:N2}"

As Bas mentioned in his answer, string interpolation doesn't support template string. Actually, it has no built in support for that. Fortunately it exists in some great libraries.


SmartFormat.NET for example has support for named placeholders:

Smart.Format("{Name} from {Address.City}, {Address.State}", user)

// The user object should at least be like that

public class User
{
public string Name { get; set; }
public Address Address { get; set; }
}

public class Address
{
public string City { get; set; }
public string State { get; set; }
}

It is available on NuGet and has excellent documentation.


Mustache is also a great solution. Bas has described its pros well in his answer.

Named string formatting in C#

There is no built-in method for handling this.

Here's one method

string myString = "{foo} is {bar} and {yadi} is {yada}".Inject(o);

Here's another

Status.Text = "{UserName} last logged in at {LastLoginDate}".FormatWith(user);

A third improved method partially based on the two above, from Phil Haack

C# Formatting - How to correctly format a name? I.e. forename or surname

Does it really matter? If a user doesn't care whether their name is all upper case or all lower case then I'd suggest that you don't need to worry about that either.

Users who do care about how their name is capitalised will presumably enter their name with care.

If you start to mess around with capitalisation then there's the risk of getting it wrong and offending a user.

Surely there are other aspects of the system that warrant more attention...

String interpolation using named parameters in C#6


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.

C# Referencing a variable type, name and value in a format string

Apart from Marc Gravell's comments, you could have something along these lines:

    public class SomeInvoiceData
{
public int InvoiceID { get; set; }
public System.DateTime InvoiceDate { get; set; }
public string InvoiceName { get; set; }
}

public static class Value
{
public static string Formatted(this object o)
{
if (o is string)
{
return $"'{o.ToString()}'";
}
else if(o is DateTime)
{
return $"'{o.ToString()}'";
}
else
{
return $"{o.ToString()}";
}
}
}


public class SQLBuilder
{
private List<string> List = new List<string>();
private string Delimiter = ",";
public void AppendAll(object instance)
{
System.Reflection.PropertyInfo[] listProperty = instance.GetType().GetProperties();
foreach (var property in listProperty)
{
var pvalue = property.GetValue(instance);
var statement = $"{property.Name} = {pvalue.Formatted()}";
List.Add(statement);
}
}
public string Get()
{
return String.Join(Delimiter, List);
}
}

result is
InvoiceID = 123,InvoiceDate = '2/17/2020 10:23:04 AM',InvoiceName = 'invoice for $3.3'

Format string with meaningful markers

Please check out SmartFormat which in effect will do what you want to.

(You sayed, that you do not use replacing the human readable names with the indexes)

Example from their wiki:

String.Format references all args by index:

String.Format("{0} {1}", person.FirstName, person.LastName)

Smart.Format takes this a step further, and lets you use named placeholders instead:

Smart.Format("{FirstName} {LastName}", person)

In fact, Smart.Format supports several kinds of expressions:

Smart.Format("{FirstName.ToUpper} {LastName.ToLower}", person)

Working example requires the variables to be packed into an anonymous type:

var formatted=Smart.Format(template, new { orderNo, warehouseName, eta })

that returns correct, desired, result, with markers correctly replaced. Without the anonymous type it didn't seem to work.

Format String using List of String as an argument in C#

You can use the string.Format overload that takes a params object array argument, if the list order is guaranteed.

List<string> Person = new List<string>() {"Watson", "1001", "Female"};
string format = @"Name: {0}({1}) - {2}";
string expectedString = string.Format(format, Person.ToArray());

This outputs Name: Watson(1001) - Female



Related Topics



Leave a reply



Submit