named String.Format, is it possible?

2020-01-28 04:06发布

Instead of using {0} {1}, etc. I want to use {title} instead. Then fill that data in somehow (below I used a Dictionary). This code is invalid and throws an exception. I wanted to know if i can do something similar to what i want. Using {0 .. N} is not a problem. I was just curious.

Dictionary<string, string> d = new Dictionary<string, string>();
d["a"] = "he";
d["ba"] = "llo";
d["lol"] = "world";
string a = string.Format("{a}{ba}{lol}", d);

10条回答
爷、活的狠高调
2楼-- · 2020-01-28 04:58

You can implement your own:

public static string StringFormat(string format, IDictionary<string, string> values)
{
    foreach(var p in values)
        format = format.Replace("{" + p.Key + "}", p.Value);
    return format;
}
查看更多
Lonely孤独者°
3楼-- · 2020-01-28 04:58

It's possible now

With Interpolated Strings of C# 6.0 you can do this:

string name = "John";
string message = $"Hi {name}!";
//"Hi John!"
查看更多
beautiful°
4楼-- · 2020-01-28 05:01
static public class StringFormat
{
    static private char[] separator = new char[] { ':' };
    static private Regex findParameters = new Regex(
        "\\{(?<param>.*?)\\}",
        RegexOptions.Compiled | RegexOptions.Singleline);

    static string FormatNamed(
        this string format,
        Dictionary<string, object> args)
    {
        return findParameters.Replace(
            format,
            delegate(Match match)
            {
                string[] param = match.Groups["param"].Value.Split(separator, 2);

                object value;
                if (!args.TryGetValue(param[0], out value))
                    value = match.Value;

                if ((param.Length == 2) && (param[1].Length != 0))
                    return string.Format(
                        CultureInfo.CurrentCulture,
                        "{0:" + param[1] + "}",
                        value);
                else
                    return value.ToString();
            });
    }
}

A little more involved than the other extension method, but this should also allow non-string values and formatting patterns used on them, so in your original example:

Dictionary<string, object> d = new Dictionary<string, object>();
d["a"] = DateTime.Now;
string a = string.FormatNamed("{a:yyyyMMdd-HHmmss}", d);

Will also work...

查看更多
Lonely孤独者°
5楼-- · 2020-01-28 05:02

Why a Dictionary? It's unnecessary and overly complicated. A simple 2 dimensional array of name/value pairs would work just as well:

public static string Format(this string formatString, string[,] nameValuePairs)
{
    if (nameValuePairs.GetLength(1) != 2)
    {
        throw new ArgumentException("Name value pairs array must be [N,2]", nameof(nameValuePairs));
    }
    StringBuilder newFormat = new StringBuilder(formatString);
    int count = nameValuePairs.GetLength(0);
    object[] values = new object[count];
    for (var index = 0; index < count; index++)
    {
        newFormat = newFormat.Replace(string.Concat("{", nameValuePairs[index,0], "}"), string.Concat("{", index.ToString(), "}"));
        values[index] = nameValuePairs[index,1];
    }
    return string.Format(newFormat.ToString(), values);
}

Call the above with:

string format = "{foo} = {bar} (really, it's {bar})";
string formatted = format.Format(new[,] { { "foo", "Dictionary" }, { "bar", "unnecessary" } });

Results in: "Dictionary = unnecessary (really, it's unnecessary)"

查看更多
登录 后发表回答