在 C# 中,foreach 循环比构建字符串慢吗?

3
今天我的同事告诉我,通过使用foreach和字符串生成器(即在ascx.cs上构建整个字符串,将html代码写入字符串中),并在ascx的末尾发布它作为<%=myStringGenerateByStringBuilder%>,比直接在ascx上使用foreach更快。
<% foreach (var thing in things)
   { %>
   <div><p><%= thing.Description %></p></div>
<% }; %>

这是因为使用开放式的 <% 和闭合式的 %> 很消耗资源。

是真的吗?我不是在谈论代码管理(第二种方法是我使用的,非常干净简单),而是在谈论生成代码时的性能。


2
他/她是如何支持自己的论点的?使用了哪些来源...你们两个至少进行过性能测试吗? - adt
这只是饭局期间的闲聊 :) - markzzz
如果有差异,那可能是由于使用 StringBuilder 与多个 foreach 输出引起的,而不是多个 <% %> 结构与单个结构之间的区别。无论如何,正如其他人所说,只有一种方法可以找出答案。 - Mr Lister
如果您不明智地设置容量,StringBuilder 肯定会变慢。 - SLaks
5个回答

2

由于有很多因素需要考虑,您需要在实际网站中进行测试以确保正确性。

  • 请记住,您不一定只是构建字符串并将其返回给浏览器。
  • 如果您正在构建大文件,则可能会受益于asp.net的流式传输功能。

2

好的,接下来是一些测试:

void Main()
{
    var things = Enumerable
            .Range(1, 2000000)
            .Select(r => new Thing {Description = r.ToString()})
            .ToList();

    var times = Enumerable.Range(1, 10)
        .Select(t => new
            {   
                Method1 = Test(Method1, things),
                Method2 = Test(Method2, things),
            }
    ).ToList();
    var average = new {
            Method1 = TimeSpan.FromMilliseconds( times.Sum(t=>t.Method1.TotalMilliseconds) / times.Count),
            Method2 = TimeSpan.FromMilliseconds( times.Sum(t=>t.Method2.TotalMilliseconds) / times.Count),
    };
    average.Dump();
}

public TimeSpan Test(Action<IEnumerable<Thing>> action, IEnumerable<Thing> things)
{
    var stopWatch = new Stopwatch();
    stopWatch.Start();
    action(things);
    stopWatch.Stop();
    return stopWatch.Elapsed;
}

public void Method1(IEnumerable<Thing> things)
{
    var sb = new StringBuilder();
    using (var stringWriter = new StringWriter(sb) )
    {
        using (var htmlWriter = new HtmlTextWriter(stringWriter))
        {                   
            foreach (var thing in things)
            {
                htmlWriter.Write(thing.Description);
            }
        }
    }   
}


public void Method2(IEnumerable<Thing> things)
{
    var thingsBuilder = new StringBuilder();
    foreach ( var thing in things)
        thingsBuilder.Append(thing.Description);
    var thingsText = thingsBuilder.ToString();
    var sb = new StringBuilder();
    using (var stringWriter = new StringWriter(sb) )
    {
        using (var htmlWriter = new HtmlTextWriter(stringWriter))
        {           
            htmlWriter.Write(thingsText);                   
        }
    }   
}

public class Thing
{
    public string Description {get; set;}
}
// Define other methods and classes here

(use linq pad)

enter image description here

然而,我怀疑有人会在网页中写入20亿个字符串。 对于较小的列表,没有区别。 即使我设置了StringBuilder的容量,它仍然会更慢。 因此,直接使用HtmlTextWriter编写许多小字符串比从这些字符串构建一个字符串,然后写入它要快。


1

<%= x %> 会被编译成对 TextWriter 的调用,这会带来一些开销。因此,先构建一个更大的字符串可能会更快。反之亦然。

需要测量才能确定,任何没有经过测量的猜测都是没有根据的。


0
你的同事是对的,我尝试了相同的工作(例如在Word中添加文本)。我使用了Stringbuilder和foreach来创建字符串,只有在将其添加到Word中后,它才比在foreach中添加字符串时更快。

当我加入单词时间增长时,导致单词工作。在这里,我认为TextWriter会工作。 - Likurg

0

此外,这也取决于网站是否预编译。

在我看来,更重要的问题是将演示移动到代码后面会引入缺乏可维护性。例如,如果我需要向div添加一个类,我不应该去代码后面执行此操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接