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
aref
参数。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 });
}
}