-1

我经常有这样的代码。

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 表。

4

8 回答 8

3

除了其他建议之外,重要的是使用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 更快,在我的情况下 10% 用于 100000 个项目的选择。我不知道怎么来的,但应该是应得的。

于 2013-05-23T16:39:04.573 回答
1

此代码实际上不需要任何其他类型的实现。

代码已经足够干净,并且意图非常清楚。

@RyanWH 补充道:

当且仅当它提供必要的性能提升时,在这种情况下使用 LINQ 可能会更好。最初的问题与速度无关,所以我同意原始内容简单易懂。

于 2013-05-23T16:28:06.923 回答
1

您可以使用以下命令将所有这些折叠成一个语句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))
        )
    );
}
于 2013-05-23T16:29:24.837 回答
1

我认为使用 astring.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";
}
于 2013-05-23T16:44:03.833 回答
0

将您所拥有的内容准确地放入函数中怎么样?该实现没有任何问题,并且在任何意义上都不是“肮脏的”。将代码放在更少的行上并不一定意味着它会更好。您可以将通用项目的通用集合作为输入参数并返回字符串生成器。删除项目中所有复制粘贴的代码要比尽量减少像这样的简单例程的行数要好得多。

如果您正在谈论可能进行 XML 或 HTML 序列化,那么已经有工具可以为您做到这一点。C# 结合了一种在 XML 中包含内容的声明方式,我想有一个库可以为 HTML 做同样的事情。事实上,谷歌搜索 C# html 序列化会导致您在 stackoverflow 上找到几篇有用的帖子。

于 2013-05-23T16:37:30.117 回答
0
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");
}
于 2013-05-23T16:28:41.050 回答
0

你可以替换这个:

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);
于 2013-05-23T16:28:57.757 回答
0

这是我个人会做的改变。在我看来,我认为私有方法比尝试对所有内容进行 LINQ-idize 更具表现力。我还考虑更改常量的硬编码值,以帮助可维护性。

public string YourMethod()
{
    string text = string.Empty;
    IEnumberable<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();
}
于 2013-05-23T16:51:16.927 回答