C#泛型效率,更好的方法

C#泛型效率,更好的方法,c#,generics,collections,C#,Generics,Collections,好的,假设我有如下的课程: public class KPIObject<T> //<--This class where T is the following classes { public List<T> Data { get; set; } public string Caption { get; set; } } public class KPICycleCountAccuracyData //<--There are 20 of

好的,假设我有如下的课程:

public class KPIObject<T> //<--This class where T is the following classes
{
    public List<T> Data { get; set; }
    public string Caption { get; set; }
}

public class KPICycleCountAccuracyData //<--There are 20 of these with different names and values
{
    public string Facility { get; set; }
    public string CCAdjustedCases { get; set; }
    public string TotalCases { get; set; }
    public string CCAdjustedPercent { get; set; }
}
公共类KPIObject//两条注释

  • 无需在
    ProcessKPI
    中设置
    data
    a
    ref
    参数。
    ref
    参数仅对C#中的
    类型有意义(如果您实际为其赋值)。在这里,您只是在修改对象,以便
    ref
    除了笨拙的调用语法之外,您不会做任何事情
  • 即使
    Count
    已签名,它也不会返回负值
  • 我更喜欢
    (IEnumerable)item.Data
    而不是
    作为IEnumerable
    版本。如果后者失败,它将导致
    ArgumentNullException
    ,而实际上这是一个铸造问题
      速度 假设您谈论的是计算效率(即速度),则有两种操作可能需要改进:

      首先,在
      temp
      变量中创建
      item.Data
      的副本。当您知道生成的
      ReportData
      将永远不会被修改时,您可以直接使用item.Data,放弃昂贵的复制操作

      
      data.Add(新报表数据){
      Data=(IEnumerable)item.Data,
      Name=Name,
      Title=item.Caption})

      其次,转换为
      IEnumerable
      可能会在以后导致不必要的装箱/拆箱。查看应用程序向
      ReportData
      添加泛型类型参数是否有意义,以便您可以将其实例化为
      newreportdata()
      。这样,编译器可以更好地优化代码

      内存 通过使用continuations实现您的解决方案,您可以一次处理一个ReportData元素,而不是一次处理所有ReportData元素,从而减少内存占用。请看一下该声明,看看如何推动这种做法

      其他
      对于进一步的代码质量改进,JaredPar的回答提供了一些非常好的建议。

      只是为了弄清楚您想要的是哪种类型的效率提高:您是说您正在对
      ProcessKPI()
      进行20次调用(您在第一个代码段中指出的20种类型中,每种类型调用一次),如果再添加一个类型,则必须再添加一个对
      ProcessKPI()
      的调用,等等。?您正在寻找一种更具可伸缩性的方式来编写此代码?性能、更少的代码和内存问题。是的,如果我添加另一个类,我必须进行另一个ProcessKPI调用。不确定它的长度,但我知道您的数据参数不需要是ref,因为它不是值类型。好的,我删除了ref并更改了IEnumerable位置。我删除了ref并更改了IEnumerable位置。谢谢。我想你弄错了,我看不出这种方法有任何复制品。列表操作都是引用,字符串副本都是引用。所以他最多只能复制一些指针地址。此外,我相信你关于装箱的陈述是不合理的,除非OP正在处理列表等,当类型是引用类型时,不会发生装箱-这是1,收益率是+1information@ChrisMarisicAddRange()确实复制了所有引用,而不是完整的对象。我并不是说所有的字符串都被复制了。但每次迭代都要复制的仍然是那20个参考文献;根据列表的实现,可能位于不连续内存段中的引用。它的成本可能很小,但忽略AddRange()的复制操作肯定比忽略它要快。
      public List<ReportData>> ProcessAccountReport(GetAccountReport request)
      {
          var data = new List<ReportData>();
          ProcessKPI(data, request.KPICycleCountAccuracy, "KPICycleCountAccuracy"); //<-- 20 of these
          return data;
      }
      
      private static void ProcessKPI<T>(List<ReportData> data, ICollection<KPIObject<T>> items, string name)
      {
          if (items == null || items.Count <= 0) return;
          foreach (var item in items)
          {
              if (item.Data == null || item.Data.Count <= 0) continue;
              var temp = new List<object>();
              temp.AddRange((IEnumerable<object>)item.Data);
              data.Add(new ReportData { Data = temp, Name = name, Title = item.Caption });
          }
      }
      
      private static void ProcessKPI<T>(ICollection<ReportData> data, ICollection<KPIObject<T>> items, string name)
              {
                  if (items == null || items.Count <= 0) return;
                  foreach (var item in items.Where(item => item.Data != null && item.Data.Count > 0))
                  {
                      data.Add(new ReportData { Data = (IEnumerable<object>)item.Data, Name = name, Title = item.Caption });
                  }
              }