开发者

Is StringBuilder really faster than Aggreggate?

开发者 https://www.devze.com 2023-02-20 17:46 出处:网络
string c = tmpArr[0].Aggregate(string.Empty, (current, m) => current + (m.Name + \" \")); StringBuilder sb = new StringBuilder();
        string c = tmpArr[0].Aggregate(string.Empty, (current, m) => current + (m.Name + " "));

        StringBuilder sb = new StringBuilder();

        foreach (Mobile m in tmpArr[0])
            sb.Append(m.Name + " ");

        sb.ToString();

which of those two is faster? aggregate certainly is cleaner, but is it fast or is it the same as doing

foreach(Mobile m in tmpArr[0])
    c += m.Name + " ";

what I 开发者_如何学Creally would like to do is something like string.Join(",",tmpArr[0]), but I don't want it to concat their ToString values, just their Names, how would I do that best?

my problem with not using string.Join is I would actually have to do something like this:

        string separator = "";
        StringBuilder sb = new StringBuilder();

        foreach (Mobile m in tmpArr[0])
        {
            separator = ", ";
            sb.Append(separator + m.Name);
        }


If you append strings in a loop (c += m.Name + " ";) you are causing lots of intermediate strings to be created; this causes "telescopic" memory usage, and puts extra load on GC. Aggregate, mixed with the fluent-API of StringBuilder can help here - but as would looping with StringBuilder. It isn't Aggregate that is important: it is not creating lots of intermediate strings.

For example, I would use:

foreach (Mobile m in tmpArr[0])
        sb.Append(m.Name).Append(" ");

even fewer ;p

And for a similar example using StringBuilder in Aggregate:

string c = tmpArr[0].Aggregate(new StringBuilder(),
    (current, m) => current.Append(m.Name).Append(" ")).ToString();


I don't want it to concat their ToString values, just their Names, how would I do that best?

string.Join(",",tmpArr[0].Select(t => t.Name).ToArray())

But most of the time It. Just. Doesn't. Matter!


As string is Immutable, add operation has performance cost. This is what the StringBuilder is mainly designed for, it acts like "Mutable" String. I haven't done much benchmarking for the speed, but for memory optimizations StringBuilder is definitely better.


Aggregate runs an anonymous method against each item in the IEnumerable. This method is passed to the System-defined Func<> delegate which returns an out parameter.

It's basically like running a function that does the appending as many times.

So allocation/deallocation on the stack for the method calls etc certainly has more overhead than running a simple for/foreach loop

So, in my opinion the second method would be faster.


Aggregate itself is not the problem. The problem is you are concatenating strings in a loop. When you concatenate two strings with + operator, a new place must be allocated in memory and the two strings are copied into it. So if you use the + five times, you actually create five new strings. That's why you should use StringBuilder or Join which avoid this.

If you want to use Join along with linq for better readability, you still can, just don't use Aggregate but something like Select and ToArray.


Something like this?

string joined = string.Join(",", myItems.Select(x => x.Name).ToArray());
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号