【问题标题】:How to write this in better way?如何以更好的方式写这个?
【发布时间】:2011-11-25 07:42:41
【问题描述】:

让我们看看这段代码:

IList<IHouseAnnouncement> list = new List<IHouseAnnouncement>();
var table = adapter.GetData(); //get data from repository object -> DataTable

if (table.Rows.Count >= 1)
{
    for (int i = 0; i < table.Rows.Count; i++)
    {
        var anno = new HouseAnnouncement();
        anno.Area = float.Parse(table.Rows[i][table.areaColumn].ToString());
        anno.City = table.Rows[i][table.cityColumn].ToString();
        list.Add(anno);
    }
  }
  return list;

以更少的代码和更好的方式编写这个更好的方法(必须是:-))?也许使用 lambda(但请告诉我如何使用)?

提前致谢!

【问题讨论】:

    标签: c# design-patterns lambda


    【解决方案1】:

    仅供参考,您永远不会将新的HouseAnnouncement 添加到您的列表中,并且您的循环将永远不会为 last 行执行,但我假设这些是示例中的错误,而不是比你的实际代码。

    你可以这样做:

    return adapter.GetData().Rows.Cast<DataRow>().Select(row =>
        new HouseAnnouncement()
        {
            Area = Convert.ToSingle(row["powierzchnia"]),
            City = (string)row["miasto"],
        }).ToList();
    

    我通常追求可读性而不是简洁,但我觉得这很可读。

    请注意,虽然您仍然可以缓存 DataTable 并在 lambda 中使用 table.powierzchniaColumn,但我消除了这一点,这样您就不会使用不必要的闭包(闭包给内部实现带来了很大的复杂性的 lambda,所以我尽可能避免使用它们)。

    如果保持列引用原样对您很重要,那么您可以这样做:

    using (var table = adapter.GetData())
    {
        return table.Rows.Cast<DataRow>().Select(row =>
            new HouseAnnouncement()
            {
                Area = Convert.ToSingle(row[table.powierzchniaColumn]),
                City = (string)row[table.miastoColumn],
            }).ToList();
    }
    

    这会增加编译器生成的实际 IL 的复杂性,但应该为您解决问题。

    【讨论】:

    • 这是winnar。另外,dario,如果可能的话,看看你是否可以让你的方法返回一个 IEnumerable,然后如果他们愿意,你可以让消费者将它投射到一个列表中。您可以通过将 lambda 返回值转换为 IHouseAnnouncement 或使用 as 来让它返回一个 IEnumerable
    • "将其转换为列表" = "将其转换为列表"
    • 方法:Rows.Cast()没有出现,不会编译。
    • @dario:您使用的是 .NET 3.5 吗?如果是这样,请确保 using System.Linq 与您的其他 using 语句一起出现在文件顶部。
    • @亚当·罗宾逊。我的错,谢谢小费。但是我看到在您的解决方案中,我丢失了用于字符串表示的强列名称。有可能解决这个问题吗?
    【解决方案2】:

    你可以在 Linq 中做这样的事情:

    var table = adapter.GetData();
    var q = from row in table.Rows.Cast<DataRow>()
            select new HouseAnnouncement() 
               { Area = float.Parse(row[table.areaColumn].ToString()),
                 City = row[table.cityColumn].ToString()
               };
    return q.ToList();
    

    【讨论】:

    • 这将是最简洁、最具表现力和优雅的解决方案。
    • 不幸的是它不能编译。 DataTable.Rows 没有实现IEnumerable&lt;T&gt;,因此您必须调用Cast&lt;DataRow&gt;() 才能对其进行查询。即便如此,我还是看不出它有多简洁(因为它是三个语句而不是两个语句)。
    • 此外,您要检索数据两次。
    • 同意 Adam Robinson,不会编译。
    • 好的,你让我了解演员阵容。是的伪代码。我的观点是,与显式方法调用链相比,有些人更喜欢 Linq 语法的外观/可读性——这正是 Linq 编译的目标。
    【解决方案3】:

    您的“if 语句”不是必需的。您的“for 循环”已经处理了这种情况。

    此外,当您的表格行数为 1 时,您的“for 循环”将不会执行。这似乎是一个错误,不是设计使然,但我可能是错的。如果你想解决这个问题,只需去掉“-1”:

    for (int i = 0; i < table.Rows.Count; i++)
    

    【讨论】:

      【解决方案4】:

      嗯,一方面,您似乎有一个错误:

      for (int i = 0; i < table.Rows.Count - 1; i++)
      {
      }
      

      如果您的表有 3 行,这将在 i 小于 3 - 1 或 2 时运行,这意味着它将针对第 0 行和第 1 行运行,但不会针对第 2 行。这可能不是您的打算。

      【讨论】:

        【解决方案5】:

        只有一个 for 循环和没有 if 语句,再简单不过了:

        var table = adapter.GetData(); //get data from repository object -> DataTable
        IList<IHouseAnnouncement> list = new List<IHouseAnnouncement>(table.Rows.Count);
        
        for (int i = 0; i < list.Length; i++)
        {
           list[i] = new HouseAnnouncement();
           list[i].Area = float.Parse(table.Rows[i][table.areaColumn].ToString());
           list[i].City = table.Rows[i][table.cityColumn].ToString();
        }
        
        return list;
        

        它比 linq-version 需要更多的字符,但程序员的大脑解析得更快。 :)

        【讨论】:

          【解决方案6】:

          对我来说,可读性比简洁的代码更可取——只要性能不是牺牲品。此外,我相信以后必须维护代码的任何人也会喜欢它。
          即使我在维护自己的代码,我也不想看它,比如说几个月后,然后想“我到底想完成什么”

          【讨论】:

            【解决方案7】:

            我可能会这样做:

            var table = adapter.GetData(); //get data from repository object -> DataTable
            
            return table.Rows.Take(table.Rows.Count-1).Select(row => new HouseAnnouncement() {
                Area = float.Parse(row[table.powierzchniaColumn].ToString()),
                City = row[table.miastoColumn].ToString()
            }).ToList();
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多