在没有复制/粘贴代码的情况下实现TObjectList的排序 [英] Implementing TObjectList's sort without copy/paste code
问题描述
我有一个对节点树中的节点进行排序的过程( VirtualTreeView ) 从FMM4报告中提取的所有内存泄漏都存储在TMemoryLeakList类的对象(这些是我要排序的列表)中,这些对象存储在名为TGroupedMemoryLeakList的列表列表中,TMLL和TGMLL都扩展了TObjectList.如果我想保留能够在升序和降序之间进行选择以及在按四种不同数据类型之一进行排序之间进行选择的功能,那么我必须"实现八种不同的比较方法(4种排序类型* 2种排序方向),我继续使用主要的排序方法,因为我的TMLL列表扩展了TObjectList.主要排序方法类似于此.
I have a procedure for sorting nodes in a node tree (VirtualTreeView) All memory leaks, extracted from FMM4 report, are stored in objects of a class TMemoryLeakList(these are the list I want to sort), which are stored in a list of lists called TGroupedMemoryLeakList, and both TMLL and TGMLL extend TObjectList. If I want to keep the functionality of being able to chose between ascending and descending sort order and choosing between sorting by one of four different data types, I 'have to' implement EIGHT different comparison methods (4 sort types * 2 sort directions) which I pass on to the main sorting method, because my TMLL list extends TObjectList. The main sorting method look like this.
从GUI组合框中获取字段fSortType和fSortDirection的值. 这八个通用比较函数之一看起来像此. 剩下的七个是该版本的复制/粘贴版本.
The values for the fields fSortType and fSortDirection are acquired from the GUI comboboxes. One of those eight generic comparison functions looks like this. The seven remaining are copy/pasted variations of this one.
是否有任何合理的方法来重构大量复制粘贴代码,并且仍然保留选择特定排序类型和方向的功能?
Is there any rational way to refactor this huge amount of copy paste code and still keep the functionality of choosing a specific sort type and direction?
推荐答案
关于重构的好问题,但我不喜欢您大概正在寻找的答案.几行额外的代码行或一些额外的例程并没有错.尤其是后者,在这种情况下,命名会积极帮助提高可读性.
Nice question about refactoring, but I dislike the answer you presumably are looking for. There is nothing wrong with a few extra lines of code, or a few extra routines. Especially the latter in which case naming actively assist in more readability.
我的建议是:保留设计不变,但缩短代码:
My advice would be: leave the design as you have, but shorten the code:
function CompareSizeAsc(Item1, Item2: Pointer): Integer;
begin
Result := TMemoryLeak(Item2).Size - TMemoryLeak(Item1).Size;
end;
function CompareSizeDesc(Item1, Item2: Pointer): Integer;
begin
Result := TMemoryLeak(Item1).Size - TMemoryLeak(Item2).Size;
end;
function CompareClassNameAsc(Item1, Item2: Pointer): Integer;
begin
Result := CompareStr(TMemoryLeak(Item1).ClassName,
TMemoryLeak(Item2).ClassName);
end;
procedure TMemoryLeakList.Sort;
begin
case FSortDirection of
sdAsc:
case FSortType of
stSize: inherited Sort(CompareSizeAsc);
stClassName: inherited Sort(CompareClassNameAsc);
stCallStackSize: inherited Sort(CompareCallStackSizeAsc);
stId: inherited Sort(CompareIdAsc);
end;
sdDesc:
case FSortType of
stSize: inherited Sort(CompareSizeDesc);
stClassName: inherited Sort(CompareClassNameDesc);
stCallStackSize: inherited Sort(CompareCallStackSizeDesc);
stId: inherited Sort(CompareIdDesc);
end;
end;
end;
您不能将其缩小,然后再保持相同的可读性.
You can't get it much smaller then this ánd preserve the same level of readability.
当然,您可以按照 Arioch'The :
procedure TMemoryLeakList.Sort;
const
Compares: array[TSortDirection, TSortType] of TListSortCompare =
((CompareSizeAsc, CompareClassNameAsc, CompareCallStackSizeAsc,
CompareIdAsc), (CompareSizeDesc, CompareClassNameDesc,
CompareCallStackSizeDesc, CompareIdDesc));
begin
inherited Sort(Compares[FSortDirection, FSortType]);
end;
但是,为什么:为什么不重写QuickSort例程以消除对单独的比较例程的需要呢?
But then: why not rewrite the QuickSort routine to eliminate the need for separate compare routines?
或者,您可以向TMemoryLeak添加所有权,在这种情况下,您可以引用拥有列表及其排序方向和排序类型,以供在单个比较例程中使用.
Alternatively, you could add ownership to TMemoryLeak in which case you have a reference to the owning list and its sort direction and sort type, for use within óne single compare routine.
这篇关于在没有复制/粘贴代码的情况下实现TObjectList的排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!