在C#中返回多个匿名类型列表的最佳和最佳方法是什么?

时间:2017-11-06 09:22:34

标签: c# asp.net list generic-list

我有3个System.Collections.Generic.List<<anonymous type: System.DateTime.Week, int Count>>.

类型的列表

在我的程序中,我正在使用Type的列表(比如详情列表),其中包含从DB获取的数据。

使用此detailsList我正在创建3个单独的列表,类型为System.Collections.Generic.List<<anonymous type: System.DateTime.Week, int Count>>.

基本上这些列表的选择部分如下:

detailsList
    .Where(where_part)
    .Select(x => x.Week)
    .GroupBy(x => x.Week)
    .(x => new { Week = x.Key, Count = x.Count() })
    .ToList();

如何使用最佳方式从方法返回这些列表? 在这种情况下,此方法的返回类型是什么?

注意:返回后,我想再次单独访问这些列表,因为我需要填写3个不同的数据表来填充这些列表。

2 个答案:

答案 0 :(得分:1)

注意:这个答案的第一部分是C#6。如果使用C#7,您可以使用C#7的内置元组返回类型,如最后所述。

您的代码:

detailsList.Where(where_part).Select(x=>x.Week).GroupBy(x=>x.Week).Select(x=>x.Count)

...不选择匿名类型。这将返回IEnumerable<int>。如果你想要一个周/计数对列表,你需要这样做:

detailsList.Where(where_part).Select(x=>x.Week).GroupBy(x=>x.Week)
   .Select(x=>new {Week = x.Key, x.Count()})

无论如何,如果我理解了这个问题,你想要返回三个列表,例如(编写一个例子):

  1. 每周烘焙的蛋糕数量
  2. 每周销售的蛋糕数量
  3. 每周燃烧的蛋糕数量
  4. ...列表中的每个元素看起来都像{Week: 3, Count: 22}

    您可以使用Tuple来存储周/计数对。没有类型 System.DateTime.Week,它只是int,因此合适的Tuple将是Tuple<int, int>。因此,您将返回多个List个(或IListICollection甚至IEnumerable s。

    [令我感到震惊的是,您可能会使用这些列表查找给定“周”的“计数” - 在这种情况下,创建Dictionary<int, int>而不是创建List可能会更方便Tuple<int, int>的{​​{1}}。在这种情况下,您可以使用Select电话替换上一个ToDictionary()。]

    无论如何,您现在遇到了如何从您的方法返回三个这些列表(或词典)的问题。您有几种选择:

    1. 别。创建三种方法: - )
    2. 返回聚合列表的对象(数组,另一个列表,另一个元组,甚至是您自己的类型)。
    3. 使用3“out”参数。
    4. 无论您选择哪种方式,使用Tuple类型都可以相对轻松地声明返回值/输出参数的类型。就个人而言,我可能会创建自己的返回类型,例如:

      class CakeInfo
      {
          List<Tuple<int, int>> CakesBakedByWeek { get; private set; }
          List<Tuple<int, int>> CakesSoldByWeek { get; private set; }
          List<Tuple<int, int>> CakesBurntByWeek { get; private set; }
      
          public CakeInfo(
              IEnumerable<Tuple<int, int>> baked, 
              IEnumerable<Tuple<int, int>> sold, 
              IEnumerable<Tuple<int, int>> burnt
          )
          {
              CakesBakedByWeek = baked.ToList();
              CakesSolByWeek = sold.ToList();
              CakesBurntByWeek = burnt.ToList();
          } 
      }
      

      ...除了我永远不会只使用List :-) ...在这种情况下我会使用IReadOnlyCollection<Tuple<int, int>>IReadOnlyDictionary<int, int>

      要使用此功能,您的GetCakeInfo方法可能类似于:

      public CakeInfo GetCakeInfo()
      {
          var detailsList = ...;
      
          var baked = detailsList.Where(where_part_baked).Select(x=>x.Week).GroupBy(x=>x.Week)
             .Select(x=>new Tuple<int, int>(x.Key, x.Count()));
      
          var sold = detailsList.Where(where_part_sold).Select(x=>x.Week).GroupBy(x=>x.Week)
             .Select(x=>new Tuple<int, int>(x.Key, x.Count()));
      
          var burnt = detailsList.Where(where_part_burnt).Select(x=>x.Week).GroupBy(x=>x.Week)
             .Select(x=>new Tuple<int, int>(x.Key, x.Count()));
      
          return new CakeInfo(baked, sold, burnt);
      }
      

      (当然,您可以使用辅助方法来分解上面重复的代码。)

      <强> C#7

      如果您使用的是C#7,那么您可以通过使用元组返回类型(例如:

      )更轻松地将所有三个列表作为方法的返回值返回
      public (
          List<Tuple<int, int>> baked,
          List<Tuple<int, int>> sold,
          List<Tuple<int, int>> burnt
      ) GetCakeInfo()
      {
          ...
          return (baked, sold, burnt);
      }
      

      你会这样称呼:

      (List<Tuple<int, int>> baked, List<Tuple<int, int>> sold, List<Tuple<int, int>> burnt) = GetCakeInfo();
      

      ...或...

      var cakeLists = GetCakeInfo();
      var baked = cakeLists.baked;
      // ...
      

      此外,您可以使用新的ValueTuple类型而不是旧的Tuple类型作为列表元素。所以:

      public (
          List<(int week, int count)> baked,
          List<(int week, int count)> sold,
          List<(int week, int count)> burnt
      ) GetCakeInfo()
      {
          ...
          return (baked, sold, burnt);
      }
      

答案 1 :(得分:0)

您可以创建与您的输出匹配的视图模型,并使用它创建StepExecutionListener。然后你可以退货。