我经常有这样的代码。
StringBuilder sb=new StringBuilder();
IEnumberable<MyWidget> MyWidgets=GetMyWidgets();
if(MyWidgets.Count!=0)
{
sb.Append("This is header text");
foreach(MyWidget widget in MyWidgets)
{
sb.Append("This is info about widget: "+widget.SomeInfo);
}
sb.Append("This is footer text");
}
有什么方法可以让它更干净吗?也许使用 Lambda 表达式或匿名函数(我对这些不熟悉,所以一个例子会有所帮助)?
一个现实世界的示例是,如果对象集合中存在项目,则编写 HTML 表格。
除了其他建议之外,重要的是使用
Any
而不是 Count
if (MyWidgets.Any())
{
sb.Append("This is header text");
sb.Append(string.Concat("", MyWidgets.Select(x => "This is info about widget: " + x.SomeInfo)));
sb.Append("This is footer text");
}
对于少量数据,原始版本的运行速度会更快,在我的例子中,对于 100 个元素,速度要快两倍。但对于较大的数量,Linq 速度更快,在我的例子中,100000 个项目选择的速度为 10%。我不知道怎么会这样,但应该是伯爵的原因。
您可以使用
string.Join
将所有这些合并到一个语句中:
if(MyWidgets.Count() != 0) {
sb.AppendFormat(
"This is header text\n{0}This is footer text\n"
, string.Join(
"\n"
, MyWidgets.Select(w => string.Format("This is info about widget: {0}\n", w))
)
);
}
我认为使用
string.Join
会提高可读性。而且,这样一来,您就不再执行许多附加操作,简单的字符串连接就可以了。
string str = "";
IEnumerable<MyWidget> MyWidgets=GetMyWidgets();
if(MyWidgets.Any())
{
str += "This is header text\n";
str += string.Join("\n", MyWidgets.Select(x => "This is info about widget: "
+ x.SomeInfo));
str += "\nThis is footer text";
}
这段代码实际上不需要任何其他类型的实现。
代码已经足够干净了,意图也非常明确。
@RyanWH 补充:
在这种情况下使用 LINQ 可能会更好,当且仅当它提供必要的性能提升时。不过,最初的问题与速度无关,所以我同意原始内容简单且易于理解它的作用。
StringBuilder sb = new StringBuilder();
List<MyWidget> MyWidgets = GetMyWidgets().ToList();
if(MyWidgets.Count!=0)
{
sb.Append("This is header text");
MyWidgets.Foreach(w => sb.Append("This is info about widget: " + w.SomeInfo));
sb.Append("This is footer text");
}
你可以替换这个:
foreach(MyWidget widget in MyWidgets)
{
sb.Append("This is info about widget: "+widget.SomeInfo);
}
有了这个:
MyWidgets.ToList().ForEach(x => sb.Append("This is info about widget: "+ x.SomeInfo);
将现有的内容准确地放入函数中怎么样? 这个实现没有任何问题,而且从任何意义上来说都不是“肮脏”的。 将代码放在更少的行数并不一定意味着它更好。 您可以将通用项的通用集合作为输入参数并返回字符串生成器。 删除项目中所有复制粘贴的代码比最小化像这样的简单例程的行数要好得多。
如果您正在谈论可能进行 XML 或 HTML 序列化,那么已经有工具可以为您做到这一点。 C# 结合了一种在 XML 中包含内容的声明性方式,我想有一个库可以对 HTML 执行相同的操作。 事实上,谷歌搜索 C# html 序列化可以让您在 stackoverflow 上找到一些有用的帖子。
这是我个人会做的改变。在我看来,我认为私有方法比尝试 LINQ 化所有内容更具表现力。
我还考虑更改常量的硬编码值,以帮助维护。
public string YourMethod()
{
string text = string.Empty;
IEnumerable<MyWidget> MyWidgets = GetMyWidgets();
if (MyWidgets.Any())
{
text += "This is header text";
text += GetInfoFromWidgets(MyWidgets);
text += "This is footer text";
}
return text;
}
private string GetInfoFromWidgets(IEnumerable<MyWidget> widgets)
{
StringBuilder sb = new StringBuilder();
foreach (MyWidget widget in MyWidgets)
{
sb.Append("This is info about widget: "+widget.SomeInfo);
}
return sb.ToString();
}