Assume we have
string one = "1";
string two = "2";
string three = "3";
And we want to get the result string
result = "1, 2, 3"
by building it from the above three variables.
I know I can do it like this
result = one + ", " + two + ", " + three;
but as far as I understand, then a lot of strings are generated and thrown away again (first 1, then 1,, then 1, 2, then 1, 2,, then 1, 2, 3). I know I can use a StringBuilder to prevent creating new strings all the time, but this is also not what I am looking for.
In my case, I know from the start how the string will look, I only need to put references of the variables into the result string.
I know I have seen a syntax before (C#). I think it looks a bit like this:
result = "{0}, {1}, {2}", one, two, three
Questions:
What is the syntax?
What is the correct name for putting a string together from pieces when the pattern is known? I assume there is a more specific word than "concatenate". In my understanding, "concatenate" is something you want to do at runtime, when you don't know in the beginning which or how many strings are to be connected.
- Is there a difference in performance or memory usage compared to using a StringBuilder? (see https://stackoverflow.com/a/299541/5333340 - it seems string.Concat is faster.)
Here is the string.Join approach. This avoids the redundant inserting of the seperator compared to your required String.Format
string one = "1";
string two = "2";
string three = "3";
string result = string.Join(", ", one, two, three);
in addition to string.join and string.format, you could also use interpolated strings which looks cleaner than string.format in many scenarios - e.g.
result = $"{one}, {two}, {three}";
What is the syntax?
var result = string.Format("{0}, {1}, {2}", one, two, three);
or (C# 6.0 string interpolation, which is just syntactic sugar for string.Format)
var result = $"{one}, {two}, {three}";
What is the correct name for putting a string together from pieces when the pattern is known? I assume there is a more specific word than "concatenate". In my understanding, "concatenate" is something you want to do at runtime, when you don't know in the beginning which or how many strings are to be connected.
String formatting or string interpolation.
Is there a difference in performance or memory usage compared to using a StringBuilder?
As of .NET 4.0, string.Format uses a cached StringBuilder internally, so the performance difference is minimal. For very large and/or very many strings, using a raw StringBuilder will be fastest, but for most cases, string.Format will be good enough in terms of performance, and a lot more readable.
The syntax you are looking for is
result = String.Format("{0}, {1}, {2}", one, two, three);
Related
The ReadOnlySpan<char> is said to be perfect for parsing so I tried to use it and I came across a use case that I don't know how to handle.
I have a command-line string where the argument prefix - and the separator (space) are escaped (I know I could quote them here but for the sake of this problem let's assume it's not an option):
var str = #"foo -bar \-baz\ qux".AsMemory();
The tokenizer should return the following tokens:
foo - command name
bar - argument name
-baz qux - argument value
Cases 1 & 2 are simple because here I can just use str.Slice(i, length) but how can I create the 3rd case and return only a single ReadOnlySpan<char>? The Slice method doesn't allow me to specify multiple start/length ranges which would be necessary in order to jump over the escape char \.
Example:
str.Slice((10, 4), (15, 3));
where (10,4) = "-bar" and (15,3) = " qux"
With StringBuilder you can just skip a couple of characters and Append the others later. How would I achieve the same result with ReadOnlySpan<char>?
A Span/ReadOnlySpan is a contiguous block of memory. It cannot contain multiple ranges. This design is necessary for performance. Span/ReadOnlySpan is supposed to be roughly as fast as an array is. Arrays are fast because they are contiguous memory blocks with no further abstractions.
I don't see a way to do this without allocating a new string. You can use Span/ReadOnlySpan for all contiguous substrings but it seems your parsing problem is not suitable to use span to store results.
have a look at:
https://github.com/nemesissoft/Nemesis.TextParsers
and more precisely at:
TokenSequence.cs
Usage:
var tokens = "ABC|CD\|E".AsSpan().Tokenize('|', '\\', false); //no allocation. Result in 2 elements: "ABC", "CD\|E".
Consume via:
var result = new List<string>();
foreach (var part in tokens)
result.Add(part.ToString());
Unescaping can be done via:
ParsedSequence.cs
or
SpanParserHelper.UnescapeCharacter()
Hope this helps
:barbosza!barbosza#barbosza.tmi.twitch.tv PRIVMSG #pggamesbr :My text
I want the part after the second ':', but i can't split by ':' because sometimes contains it too.
You can split and specify the maximum number of items, so that everything after the second colon ends up in the third item:
string[] parts = str.Split(new char[]{':'}, 3);
The part after the second colon is now in parts[2].
I guess that "he contains it too" means "My text contains it too".
In that case, do this
string toFind = "#pggamesbr :";
string myText = myString.Substring(myString.IndexOf(toFind) + toFind.Length);
I like Guffa's simple Split solution, and would go with that if this is all you need here. But, just for fun...
If you run into a lot of odd cases like this -- things you wish were easier to do with strings -- you can consider adding extension methods to handle them. E.g.,
using System;
public static MyStringExtentions
{
public static string After(this string orig, char delimiter)
{
int p = orig.indexOf(delimiter);
if (p == -1)
return string.Empty;
else
return orig.Substring(p + 1);
}
}
And then, in your existing code, as long as you have a using directive to include reference access to MyStringExtentions's definition:
string afterPart = myString.After(':').After(':');
Disclaimer: I didn't actually test this. Some tuning may be required. And it could probably be tuned to be more efficient, etc.
Again, this is probably overkill for this one problem. (See Guffa's perfectly good simple answer for that.) Just tossing it out for when you find yourself with lots of these and want a common way to make them available.
Ref. Extension Methods (C# Programming Guide)
Trying to determine if it's a better practice to use string.Format in place of concatenating strings and if so, why is this? Also, are their advantages/disadvantages to one or the other that I should be aware of?
This:
string foo = "I" + " am " + " a " + " string.";
or:
string bar = string.Format("{0} am a {1}.", "I", "string");
Obviously oversimplified examples, just wanting to be clear.
The "best practice" should be the thing that makes your code the most readable and maintanable. The performance difference between concatenating strings versus using string.Format versus using a StringBuilder is so small that it's essentially irrelevant.
Assuming the first method was not optimized at compile time, because strings are immutable it will create many intermediate strings. It'll work from left to right so there will first be "I am ", then "I am a ", and finally "I am a string." which is stored in foo.
String.format will not make intermediate strings. To my understanding it does all the manipulation in a char[] which is then made immutable by being made a String.
I am working on a console application, that receives a pretty long list of parameters. For debugging purpose I need to print the parameters passed to a an output file. Right now, I am using the following code to concat command line parameters.
static void Main(string[] args)
{
string Params = string.Empty;
foreach(string arg in args)
{
Params += arg + ",";
}
}
Is there any better way to accomplish this?
What about
Params = string.Join(",", args);
Your foreach approach is not very performant. Since a string is immutable, that means for each iteration of the loop, the string will get thrown away for garbage collection, and a new string will be generated. In the string.Join case, only one string will be generated.
Inside the loop, to get around the same performance, you will have to use a StringBuilder, but in this case it's really no reason not to use string.Join since the code will be much more readable.
You could use this piece of code
String.Join(", ", Environment.GetCommandLineArgs())
You can use String.Join(",",args)
All of the answers here combining the arguments with a single comma will work, but I found that approach lacking somewhat because there's not a clear indicator of "quoted arguments" and those that might contain a comma.
Using the example: Foo.exe an example "is \"fine\", too" okay
The simple join suggestions will yield: an, example, is "fine", too, okay. Not bad, but not very clear and somewhat misleading.
Here's what I threw together that works well enough for me. I'm sure it could be improved further.
String.Join(", ", (from a in args select '"' + a.Replace("\"", #"\""") + '"'));
It returns the string: "an", "example", "is \"fine\", too", "okay". I think this does a better job indicating the actual parameters.
String params = String.Join(",", args);
You should use:
string.Join(",", args);
Strictly speaking the Join function creates a StringBuilder with capacity strings.Length * 16 (this 16 is a fixed number). If you have different args maximum size and if performance is crucial to you, use a StringBuilder with a specific capacity.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How should I concatenate strings?
There are several ways to concat strings in everyday tasks when performance is not important.
result = a + ":" + b
result = string.Concat(a, ":", c)
result = string.Format("{0}:{1}", a, b);
StringBuilder approach
... ?
what do you prefer and why if efficiency doesn't matter but you want to keep the code most readable for your taste?
It depends on the use. When you just want to concat two strings, using a + b is just much more readable than string.Format("{0}{1}", a, b). However, it is getting more complex, I prefer using string.Format. Compare this:
string x = string.Format("-{0}- ({1})", a, b);
against:
string x = "-" + a + "- (" + b + ")";
I think that in most cases it is very easy to spot the most readable way to do things. In the cases where it is debatable which one is more readable, just pick one, because your boss isn't paying for these pointless discussions ;-)
string.Format for me, but in practice I use whichever is fit for purpose, taking into account performance and readability.
If it was two variables I'd use.
string.Concat(str1, str2);
If it contained a constant or something that requires formatting then.
string.Format("{0} + {1} = {2}", x, y, x + y);
Or for something like an SQL query
string SqlQuery = "SELECT col1, col2, col3, col4" +
"FROM table t " +
"WHERE col1 = 1";
And string builder when performance matters.
String.Format(...) is slowest.
For simple concatenations which don't take place in a loop, use String.Concat(...) or the + operator, which translate to the same under the hood, afaik. What is more readable is very subjective.
Using a StringBuilder for simple concatenations is over-the-top for simple concatenations as well and has most likely too much overhead. I'd only use it in a loop.
For something like this (which I'm guessing is being sent to the UI), I would definitely prefer String.Format. It allows the string to be internationalized easy; you can grep for calls to String.Format and replace them with your translating format.
My personal preference is:
I find the + approach the most readable and only use Format() or a StringBuilder if there is a good reason (i18n, performance etc) for it. I (almost) never use Concat.
I think I find the + approach easier to read than Format() simply because I don't have to skip ahead to the end to see what variables are put into in the {} place-holders. And if the place-holders aren't in numeric order, it gets even harder to read imo.
But I guess for larger projects it makes sense to simply enforce using Format by a style guide just in case the code might be (re-)used in a project requiring i18n later on.
string.Format
for few concats. for more I use
StringBuilder approach
even if performance is not important. there is a team agreement I have to follow
I prefer String.Format for small strings, and StringBuilder for larger ones. My main reason is readability. It's a lot more readable to me to use String.Format (or StringBuilder.AppendFormat()), but I have to admit that that is just personal preference.
For really big text generation, you might want to consider using the new (VS2010) T4 Preprocessed Templates - they are really nice.
Also, if you're ever in VB.NET, I like the XML literal technique Kathleen Dollard talked about in episode 152 of hanselminutes.
Prefer to use:
String.Concat for simple concatenations like String.Concat("foo", bar);
String.Format for complex formatting like String.Format("{1}", url, text);
StringBuilder for massive concatenations like:
var sb = new StringBuilder();
sb.AppendLine("function fooBar() {");
sp.AppendLine(String.Join(Environment.NewLine, blah));
sp.AppendLine("}");
page.RegisterClientScript(page.GetType(), sb.ToString());
Prefer to avoid "foo" + "bar" (as well as if (foo == "bar"). And especially String.Format("{0}{1}", foo, bar) and
throw new Exception("This code was" +
"written by developer with" +
"13\" monitor");