问题描述
我最近在阅读有关函数式编程的文章。而且我最常说的是它带来了很多好处,但是我有一些性能方面的顾虑,例如在渲染非常大的字符串(例如在html页面中连接很多字符串)时。 通常我会使用String builder。但是在遵循功能性编程范例的同时我无法使用它。
效果欠佳的代码:
如您所见,ToListItem
和ToUl
是纯函数
class Program
{
static string ToListItem(string s)
{
return "<li>" + s + "</li>";
}
static string ToUl(string[] items)
{
return "<ul>" + String.Join("",items.Select(x => ToListItem(x))) + "</ul>";
}
static void Main(string[] args)
{
string[] items = new string[]
{
"Apple","Orange","Banana"
};
string htmlUl = ToUl(items);
Console.WriteLine(htmlUl);
}
}
快捷代码
但是您可以看到ToListItem
和ToUl
不再是纯函数,我无法提供在纯函数中使用StringBuilder
的解决方案
class Program
{
static void ToListItem(string s,StringBuilder sb)
{
sb.Append("<li>" + s + "</li>");
}
static void ToUl(string[] items,StringBuilder sb)
{
sb.Append("<ul>");
foreach (var item in items)
ToListItem(item,sb);
sb.Append("</ul>");
}
static void Main(string[] args)
{
string[] items = new string[]
{
"Apple","Banana"
};
StringBuilder sb = new StringBuilder();
ToUl(items,sb);
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();
}
}
您可以像这样使用它:
var list = new List<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");