C# 如何在函数式编程中使用StringBuilder?

C# 如何在函数式编程中使用StringBuilder?,c#,functional-programming,stringbuilder,C#,Functional Programming,Stringbuilder,我最近在读函数式编程。我大多数人都说它有很大的好处,但是我有一些性能方面的问题,比如当呈现一个非常大的字符串时,比如说一个html页面,其中我连接了很多字符串。 通常我会使用字符串生成器。但我不能在仍然遵循函数式编程范式的情况下使用它 性能差代码: 正如您所看到的,tolistem和ToUl都是纯函数 类程序 { 静态字符串ToListItem(字符串s) { 返回“”+s+””; } 静态字符串ToUl(字符串[]项) { 返回“”+String.Join(“,items.Select(x=>

我最近在读函数式编程。我大多数人都说它有很大的好处,但是我有一些性能方面的问题,比如当呈现一个非常大的字符串时,比如说一个html页面,其中我连接了很多字符串。 通常我会使用字符串生成器。但我不能在仍然遵循函数式编程范式的情况下使用它

性能差代码:
正如您所看到的,
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不太可能是适合您的情况的正确解决方案。如果可以,则构建一个可以序列化为标记的类型作为树。