C# 编译器如何处理拆分?

发布于 2024-12-01 04:32:22 字数 387 浏览 1 评论 0原文

我有一个 List,我正在迭代并拆分每个项目,然后将其添加到 StringBuilder 中。

foreach(string part in List)
{
   StringBuilder.Append(part.Split(':')[1] + " ");
}

所以我的问题是通过这种分割创建了多少个字符串?所有的拆分都会产生两个项目。所以...我想它将创建一个 string[2] 然后创建一个空字符串。但是,它是否会创建 string[1] + " " 的串联,然后将其添加到 StringBuilder 或者这是优化的?

I have an List<string> that I am iterating through and splitting on each item then adding it to a StringBuilder.

foreach(string part in List)
{
   StringBuilder.Append(part.Split(':')[1] + " ");
}

So my question is how many strings are created by doing this split? All of the splits are going to produce two items. So... I was thinking that it will create a string[2] and then an empty string. But, does it then create the concatenation of the string[1] + " " and then add it to the StringBuilder or is this optimized?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

疾风者 2024-12-08 04:32:22

该代码实际上与此等效:

foreach(string part in myList)
{
   sb.Append(string.Concat(part.Split(':')[1], " "));
}

所以是的,将创建一个附加的字符串,表示分割的第二部分和空字符串的串联。

包括原始的 string,您还拥有通过调用 Split() 创建的两个字符串,以及对文字字符串 " " 的引用,将从程序集元数据加载。

您只需按顺序 Append 分割结果和空字符串即可节省对 Concat() 的调用:

sb.Append(part.Split(':')[1]).Append(" ");

请注意,如果您仅使用字符串文字,则 < em>编译器会为你做一项优化:

sb.Append("This is " + "one string");

实际上编译为

sb.Append("This is one string");

The code is actually equivalent to this:

foreach(string part in myList)
{
   sb.Append(string.Concat(part.Split(':')[1], " "));
}

So yes, an additional string, representing the concatenation of the second part of the split and the empty string will be created.

Including the original string, you also have the two created by the call to Split(), and a reference to the literal string " ", which will be loaded from the assembly metadata.

You can save yourself the call to Concat() by just Appending the split result and the empty string sequentially:

sb.Append(part.Split(':')[1]).Append(" ");

Note that if you are only using string literals, then the compiler will make one optimzation for you:

sb.Append("This is " + "one string");

is actually compiled to

sb.Append("This is one string");
没有心的人 2024-12-08 04:32:22

每个项目 3 个额外字符串

  • part[0];
  • part[1];
  • part[1] + " "

最少的分配可能是完全避免所有临时分配,但通常的微优化警告适用。

var start = part.IndexOf(':') + 1;
stringbuilder.Append(part, start, part.Length-start).Append(' ');

3 extra strings for every item

  • part[0];
  • part[1];
  • part[1] + " "

the least allocations possible would be to avoid all the temporary allocations completely, but the usual micro-optimization caveats apply.

var start = part.IndexOf(':') + 1;
stringbuilder.Append(part, start, part.Length-start).Append(' ');
晨曦慕雪 2024-12-08 04:32:22

您将原始字符串“split” - 1 个字符串

您将“split”拆分为两个 - 2 个字符串

您将 split 的两个部分连接在一起 - 1 个字符串

字符串生成器不会创建新字符串。

当前代码使用 4 个字符串,包括原始代码。

如果你想保存一个字符串,请执行以下操作:

StringBuilder.Append(part.Split(':')[1]);
StringBuilder.Append(" ");

You have the original string 'split' - 1 string

You have the 'split' split into two - 2 string

You have the two parts of split joined - 1 string

The string builder does not create a new string.

The current code uses 4 strings, including the original.

If you want to save one string do:

StringBuilder.Append(part.Split(':')[1]);
StringBuilder.Append(" ");
反差帅 2024-12-08 04:32:22

这段代码:

foreach(string part in List)
{
   StringBuilder.Append(part.Split(':')[1] + " ");
}

相当于:

foreach(string part in List)
{
   string tmp = string.Concat(part.Split(':')[1], " ");
   StringBuilder.Append(tmp);
}

所以是的,它不必要地创建了一个字符串。这会更好,至少就生成的字符串数量而言:

foreach(string part in List)
{
   StringBuilder.Append(part.Split(':')[1])
                .Append(" ");
}

This code:

foreach(string part in List)
{
   StringBuilder.Append(part.Split(':')[1] + " ");
}

Is equivalent to:

foreach(string part in List)
{
   string tmp = string.Concat(part.Split(':')[1], " ");
   StringBuilder.Append(tmp);
}

So yes, it's creating a string needlessly. This would be better, at least in terms of the number of strings generated:

foreach(string part in List)
{
   StringBuilder.Append(part.Split(':')[1])
                .Append(" ");
}
感悟人生的甜 2024-12-08 04:32:22

因此,对于列表中的每个值(n,在代码中称为 part),您要分配:

  1. x(我假设 2)个字符串分裂。
  2. 用于连接的 n 个字符串。
  3. StringBuilder 的大约 n + 1 个字符串;但可能要少得多。

因此,最后有 nx + n + n + 1,并假设拆分始终会产生两个值 4n + 1

改进这一点的一种方法是:

foreach(string part in List) 
{
    var val = part.Split(':')[1];
    StringBuilder.EnsureCapacity(StringBuilder.Length + val.Length + 1);
    StringBuilder.Append(val);
    StringBuilder.Append(' ');
}

这使其成为3n + 1。这是一个粗略的估计,因为 StringBuilder 在空间不足时分配字符串 - 但如果您EnsureCapacity,您将防止它出错

So for each value in the list (n, known as part in your code) you are allocating:

  1. x (I assume 2) strings for the split.
  2. n strings for the concatenation.
  3. Roughly n + 1 string for the StringBuilder; probably much less though.

So you have nx + n + n + 1 at the end, and assuming the split always results in two values 4n + 1.

One way to improve this would be:

foreach(string part in List) 
{
    var val = part.Split(':')[1];
    StringBuilder.EnsureCapacity(StringBuilder.Length + val.Length + 1);
    StringBuilder.Append(val);
    StringBuilder.Append(' ');
}

This makes it 3n + 1. It is a rough estimate as StringBuilder allocates strings as it runs out of space - but if you EnsureCapacity you will prevent it from getting it wrong.

唱一曲作罢 2024-12-08 04:32:22

也许确定它是如何编译的唯一方法是构建它并使用 Refactor 再次反编译它以查看它的内部处理方式。无论如何,请记住,它可能不会对整个应用程序的性能产生影响。

Probably the only way to be sure about how this is compiled is to build it and decompile it again with Refactor to see how it's internally handled. Anyway have in mind that probably it does not have impact on the whole app performance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文