C# 如何在函数式编程中使用StringBuilder?
我最近在读函数式编程。我大多数人都说它有很大的好处,但是我有一些性能方面的问题,比如当呈现一个非常大的字符串时,比如说一个html页面,其中我连接了很多字符串。 通常我会使用字符串生成器。但我不能在仍然遵循函数式编程范式的情况下使用它 性能差代码:C# 如何在函数式编程中使用StringBuilder?,c#,functional-programming,stringbuilder,C#,Functional Programming,Stringbuilder,我最近在读函数式编程。我大多数人都说它有很大的好处,但是我有一些性能方面的问题,比如当呈现一个非常大的字符串时,比如说一个html页面,其中我连接了很多字符串。 通常我会使用字符串生成器。但我不能在仍然遵循函数式编程范式的情况下使用它 性能差代码: 正如您所看到的,tolistem和ToUl都是纯函数 类程序 { 静态字符串ToListItem(字符串s) { 返回“”+s+””; } 静态字符串ToUl(字符串[]项) { 返回“”+String.Join(“,items.Select(x=>
正如您所看到的,
tolistem
和ToUl
都是纯函数
类程序
{
静态字符串ToListItem(字符串s)
{
返回“”+s+” ”;
}
静态字符串ToUl(字符串[]项)
{
返回“”+String.Join(“,items.Select(x=>tolistem(x)))+”
”;
}
静态void Main(字符串[]参数)
{
字符串[]项=新字符串[]
{
“苹果”,
“橙色”,
“香蕉”
};
字符串htmlUl=ToUl(项目);
控制台写入线(htmlUl);
}
}
更快的代码但是正如您所看到的,
tolistem
和ToUl
不再是纯函数,我无法提供在纯函数中使用StringBuilder
的解决方案
类程序
{
静态无效ToListItem(字符串s、StringBuilder sb)
{
某人加上(“”+s+“ ”);
}
静态void ToUl(字符串[]项,StringBuilder sb)
{
某人加上(“”);
foreach(项目中的var项目)
Tolistem(项目,sb);
某人追加(“
”);
}
静态void Main(字符串[]参数)
{
字符串[]项=新字符串[]
{
“苹果”,
“橙色”,
“香蕉”
};
StringBuilder sb=新的StringBuilder();
(物品、某人);
Console.WriteLine(sb.ToString());
}
}
所以我的问题是:
是否可以以函数式编程方式使用StringBuilder?怎么用?如果不是,还有什么可供选择的性能解决方案?
更新1
我列举了一些例子。这里的性能并不重要,但随着列表线性增长,性能差距将呈指数增长。这并不能准确地解决上述情况,但它提供了一个基线,您可以在此基础上使用页眉和页脚参数为您的情况构建一些内容
using System;
using System.Collections.Generic;
using System.Text;
public static class FunctionalStringBuilder
{
public static string BuildString<T>(this IEnumerable<T> enumerable, Func<T, string> response)
{
var builder = new StringBuilder();
foreach (var item in enumerable)
{
builder.Append(response(item));
}
return builder.ToString();
}
}
使用系统;
使用System.Collections.Generic;
使用系统文本;
公共静态类FunctionalStringBuilder
{
公共静态字符串BuildString(此IEnumerable可枚举,Func响应)
{
var builder=新的StringBuilder();
foreach(可枚举中的变量项)
{
附加(响应(项目));
}
返回builder.ToString();
}
}
您可以这样使用它:
var list = new List<Employee>
{
AutoFaker.Generate<Employee>(),
AutoFaker.Generate<Employee>(),
AutoFaker.Generate<Employee>(),
AutoFaker.Generate<Employee>()
};
var result = list.BuildString(
e => $"Employee Id: {e.Id}, Name: {e.Name}, DateOfBirth: {e.DateOfBirth}\n");
var list=新列表
{
AutoFaker.Generate(),
AutoFaker.Generate(),
AutoFaker.Generate(),
AutoFaker.Generate()
};
var result=list.BuildString(
e=>$“员工Id:{e.Id},姓名:{e.Name},出生日期:{e.DateOfBirth}\n”);
我不确定您为什么认为StringBuilder
不能用于功能范式风格的编码?你能详细说明一下吗?请添加一些代码,这样会更容易理解你遇到的问题have@Fildor因为当我调用stringBuilder.Add时,我正在更改stringBuilder的状态,当我有复杂的逻辑时,我需要有多个函数,要使用stringBuilder,我通常必须将其作为参数传递,并在内部调用Add函数违反了纯函数的函数编程规则。所以,问题是“我可以在FP中使用对象引用作为参数吗?”答案是“不”。在我看来,你已经遇到了FP的概念,现在正试图把它塞进任何地方。请不要那样做。如果您想使用纯FP,请在F#等FP语言中使用,否则请接受在C#等OOP语言中尝试使用纯FP始终是一种折衷方案。有趣的解决方案。。但它并不完整。如果树很深怎么办。然后在某个时刻,我将递归调用BuildString并传递字符串。字符串将变长,性能将下降。我正在寻找一种方法,将字符串生成器传递给与FP相关的多个函数。但我想这毕竟是不可能的:/@DiaaEddin说得好。我看到了这种可能性。然而,仅仅因为可以递归调用方法并不意味着您应该这样做。@DiaaEddin不确定您是否可以使用这些工具,但我突然想到,StringBuilder不太可能是适合您的情况的正确解决方案。如果可以,则构建一个可以序列化为标记的类型作为树。