Latheesan
Latheesan

Reputation: 24116

Multi-line string literal format gives me error - Input string was not in a correct format

I have the following variable:

var setting = 
$@"worker_processes     {{0}};
worker_rlimit_nofile    {{1}};
error_log               logs/{{2}} {{3}};

events
{{
    worker_connections {{4}};
    multi_accept {{5}};
}}";

When I do the following String.Format() operation on it:

return string.Format(setting,
    this.worker_processes,
    this.worker_rlimit_nofile,
    this.error_log_file,
    this.error_log_level,
    this.worker_connections
    this.multi_accept ? "on" : "off");

I get the following error: Input string was not in a correct format.

Any ideas?


EDIT - Fixed

Thanks to Jon Skeet, I have arrived at this solution without using String.Format():

return 
$@"worker_processes         { this.worker_processes };
    worker_rlimit_nofile    { this.worker_rlimit_nofile };
    error_log               logs/{ this.error_log_file } { this.error_log_level };

    events
    {{
        worker_connections { this.worker_connections };
        multi_accept { (this.multi_accept ? "on" : "off") };
    }}";

Upvotes: 0

Views: 753

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1500065

It's unclear exactly what's going on as there's version confusion, but I suspect you just want:

var setting = 
@"worker_processes     {0};
worker_rlimit_nofile    {1};
error_log               logs/{2} {3};

events
{{
    worker_connections {4};
    multi_accept {5};
}}";

Now the braces for the events block will still be escaped, but the rest will be treated as format specifiers.

Here's a full example:

using System;

class Test
{
    static void Main(string[] args)
    {
        var setting = 
@"worker_processes     {0};
worker_rlimit_nofile    {1};
error_log               logs/{2} {3};

events
{{
    worker_connections {4};
    multi_accept {5};
}}";
        string text = string.Format(setting, 10, true, "log.txt", "debug", 20, false);
        Console.WriteLine(text);
    }
}

Output:

worker_processes     10;
worker_rlimit_nofile    True;
error_log               logs/log.txt debug;

events
{
    worker_connections 20;
    multi_accept False;
}

Or using string interpolation from C# 6:

    return $@"worker_processes     {worker_processes};
worker_rlimit_nofile    {worker_rlimit_nofile};
error_log               logs/{error_log_file} {error_log_level};

events
{{
    worker_connections {worker_connections};
    multi_accept {multi_accept};
}}";

Upvotes: 4

David
David

Reputation: 10708

using $ activates string interpolation, which allows a string to be autoformatted according to local variables. If you want to use numeric indecies and string.Format, don't use the interpolation. Because of the interpolation, the double braces around events are escaping to single braces, which then are seen byFormat` as a format specifier, but have an invalid syntax. IF you must use the interpolation, escape these braces again (making them quadruple)

Also note that the doble braces escapes out of the format specifier, so you'll need to scrape all but the braces under "events" or they'll come back as {0}, {1}, ect in the result string.

Finally, note that you only have 4 objects being passed into Format - since your specifiers go up to 5, you'll need 6 objects or you'll run into more exceptions.

Upvotes: 2

Related Questions