3
static void BuildStrings(List<string> sentences)
{
    string name = "Tom";
    foreach (var sentence in sentences)
        Console.WriteLine(String.Format(sentence, name));
}
static void Main(string[] args)
{

    List<string> sentences = new List<string>();
    sentences.Add("Hallo {0}\n");
    sentences.Add("{0[0]} is the first Letter of {0}\n");

    BuildStrings(sentences);

    Console.ReadLine();
}

//Expected:
//Hallo Tom
//T is the first Letter of Tom

But I got:

System.FormatException: 'Input string was not in a correct format.'

How to get the first Letter of "Tom" without changing the BuildStrings Method?

ojesseus1
  • 43
  • 5
  • 2
    This isn't possible, no. – ProgrammingLlama Aug 24 '21 at 06:43
  • https://github.com/axuno/SmartFormat/wiki/SubString – mjwills Aug 24 '21 at 06:54
  • Definitly not out-of-the-box, but you could build something similar with [`FormatWith()`](https://github.com/crozone/FormatWith) and get something like `"{name:left:1}"` and call it with `"{name:left:1}".FormatWith(new { name })` by creating your own handler overload. – Oliver Aug 24 '21 at 06:57

3 Answers3

3

You really need to do something like this:

static void BuildStrings(List<string> sentences)
{
    string name = "Tom";
    foreach (var sentence in sentences)
        Console.WriteLine(String.Format(sentence, name, name[0]));
}

static void Main(string[] args)
{
    List<string> sentences = new List<string>();
    sentences.Add("Hallo {0}\n");
    sentences.Add("{1} is the first Letter of {0}\n");

    BuildStrings(sentences);

    Console.ReadLine();
}

That gives me:

Hallo Tom

T is the first Letter of Tom
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
1

It's an odd requirement and there's nothing built-in that supports this but if you really have to, you could write a method to parse the indexers like this:

public static string StringFormatExtended(string s, params object[] args)
{
    string adjusted =
        Regex.Replace(s, @"\{(\d+)\[(\d+)\]\}", delegate (Match m)
        {
            int argIndex = int.Parse(m.Groups[1].Value);
            if (argIndex >= args.Length) throw new FormatException(/* Some message here */);

            string arg = args[argIndex].ToString();

            int charIndex = int.Parse(m.Groups[2].Value);
            if (charIndex >= arg.Length) throw new FormatException(/* Some message here */);

            return arg[charIndex].ToString();
        });

    return string.Format(adjusted, args);
}

Usage:

static void BuildStrings(List<string> sentences, string name)
{
    foreach (var sentence in sentences)
        Console.WriteLine(StringFormatExtended(sentence, name));
}

static void Main(string[] args)
{
    string name = "Tom";

    List<string> sentences = new List<string>();
    sentences.Add("Hello {0}\n");
    sentences.Add("{0[0]} is the first Letter of {0}");
    sentences.Add("{0[2]} is the third Letter of {0}");

    BuildStrings(sentences, name);

    Console.ReadLine();
}

Output:

Hello Tom

T is the first Letter of Tom
m is the third Letter of Tom
0

You could add a custom format and use it instead of [0]. Look at this: Custom format - maximum number of characters

PawZaw
  • 1,033
  • 7
  • 15