我试图附加一个字符串列表(> 10),所以为了避免创建很多字符串,我使用的是StringBuilder。如果有人解释为什么会发生这种情况,那就太好了。
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var lst = new List<string>(){"A", "B", "C"};
StringBuilder sb = new StringBuilder();
lst.Select(str => sb.Append(str.ToLower()));
Console.Write("Output: {0}", sb.ToString());
}
}
答案 0 :(得分:4)
正如其他答案中所指出的,Select
的懒惰是这里的问题。我更广泛地补充说,使用副作用(例如附加到StringBuilder
)在LINQ查询中通常是一个坏主意。理想情况下,每个选择器,条件等都应该是无副作用的。
正如Gilad指出的那样,在这种情况下你可以使用string.Concat
- 但是你需要使用Select
将每个值转换为小写,除非你想在事后做到这一点(在一些极端情况下可能会有不同的结果,我怀疑)。
所以:
var list = new List<string> { "A", "B", "C" };
string result = string.Concat(list.Select(str => str.ToLower()));
或者,结果可能不同,但创建的字符串更少:
var list = new List<string> { "A", "B", "C" };
string result = string.Concat(list).ToLower();
鉴于存在string.Concat
,我不会开始使用foreach
循环或List.ForEach
等......当它内置于“{1}}循环中时,无需手动”框架。
您可能还想考虑使用ToLowerInvariant
代替ToLower
,具体取决于您要做的事情。套管非常复杂。
答案 1 :(得分:2)
使用ForEach
代替Select
:
static void Main(string[] args)
{
var lst = new List<string>() { "A", "B", "C" };
StringBuilder sb = new StringBuilder();
lst.ForEach(str => sb.Append(str.ToLower()));
Console.Write("Output: {0}", sb.ToString());
Console.ReadKey();
}
或者您可以使用LINQ Aggregate
:
var lst = new List<string>() { "A", "B", "C" };
string result = lst.Aggregate((x, y) => x + y).ToLower();
答案 2 :(得分:1)
LINQ方法Select
是lazy。
因此,lst.Select(str => sb.Append(str.ToLower()));
不会更改sb
要查看效果,您必须迭代throgh结果:
例如lst.Select(str => sb.Append(str.ToLower())).ToArray();
。
来自@thehennyy:
您还可以使用方法List.ForEach
答案 3 :(得分:0)
您还可以将.Aggregate
字符串添加到构建器中 - 使用每个.Append
返回新StringBuilder
引用的事实。
StringBuilder result = lst.Aggregate(new StringBuilder(), (sb, str) => sb.Append(str));
这样您就不会滥用.Select
迭代器,也不会对查询造成副作用。