我有一个方法接受一个数组(浮点数或双精度数),开始和结束索引,然后对startIndex到endIndex范围内的索引进行一些元素操作.
基本上它看起来像这样:
public void Update(float[] arr,int startIndex,int endIndex) { if (condition1) { //Do some array manipulation } else if (condition2) { //Do some array manipulation } else if (condition3) { if (subcondition1) { //Do some array manipulation } } }
方法比这长,并涉及将一些元素设置为0或1,或者规范化数组.
问题是我需要在那里传递float []和double []数组,并且不希望有一个重复的代码接受double [].
性能也很关键,因此我不想创建一个新的double []数组,向其投射浮点数组,执行计算,然后通过强制转换为浮点数来更新原始数组.
解决方法
你有几个选择.它们都不符合您的要求,但根据您需要的操作类型,您可能会接近.
第一种是使用泛型类型受限制的泛型方法,但您可以执行的唯一操作是有限的:
public void Update<T>(T[] arr,int endIndex) : IComarable { if (condition1) { //Do some array manipulation } else if (condition2) { //Do some array manipulation } else if (condition3) { if (subcondition1) { //Do some array manipulation } } }
并且该函数中的条件和数组操作将仅限于使用以下形式的表达式:
if (arr[Index].CompareTo(arr[OtherIndex])>0) arr[Index] = arr[OtherIndex];
这足以执行查找最小值或最大值或对数组中的项进行排序等操作.它不能做加/减/等,所以这不能说,找到平均值.您可以通过为所需的任何其他方法创建自己的重载委托来弥补这一点:
public void Update<T>(T[] arr,int endIndex,Func<T,T> Add) : IComarable { //... arr[Index] = Add(arr[OtherIndex] + arr[ThirdIndex]); }
对于你实际使用的每个操作,你需要另一个参数,我不知道它将如何执行(最后一部分将成为这里的一个主题:我没有对此进行基准测试,但性能似乎对于这个问题).
想到的另一个选择是动态类型:
public void Update(dynamic[] arr,int endIndex) { //...logic here }
这应该可行,但对于一些被称为反复的事情,你声称我不知道它会对性能产生什么影响.
您可以将此选项与另一个答案(现已删除)结合使用,以回馈某些类型的安全性:
public void Update(float[] arr,int endIndex) { InternalUpdate(arr,startIndex,endIndex); } public void Update(double[] arr,endIndex); } public void InternalUpdate(dynamic[] arr,int endIndex) { //...logic here }
另一个想法是将所有花车投射到双打:
public void Update(float[] arr,int endIndex) { Update( Array.ConvertAll(arr,x => (double)x),endIndex); } public void Update(double[] arr,int endIndex) { //...logic here }
同样,这将重新分配数组,因此,如果这会导致性能问题,我们将不得不寻找其他地方.
如果(并且仅当)所有其他都失败,并且分析器显示这是代码的关键性能部分,则可以重载该方法并实现逻辑两次.从代码维护的角度来看,这并不理想,但如果性能问题得到充分证实和记录,那么复制意大利面的问题就是值得的.我添加了一个示例注释,以指示您可能希望如何记录此内容:
/****************** WARNING: Profiler tests conducted on 12/29/2014 showed that this is a critical performance section of the code,and that separate double/float implementations of this method produced a XX% speed increase. If you need to change anything in here,be sure to change BOTH SETS,and be sure to profile both before and after,to be sure you don't introduce a new performance bottleneck. */ public void Update(float[] arr,int endIndex) { //...logic here } public void Update(double[] arr,int endIndex) { //...logic here }
这里要探讨的最后一个项目是,C#包含一个通用的ArraySegment<T>
类型,您可能会发现它对此有用.