我有2个项目可以处理相同的数据,不同的流程。主阵列几乎完全相同,略有变化,如:
// Project 1
TData1 = record
A:string;
B:integer;
C:word;
...
end;
// Project 2
TData1 = record
A:string;
B:integer;
C:word;
...
XMLNode:TXMLNode; // Extra value needed in Project 2, not needed in Project 1
end;
我想在项目之间共享众多阵列。我想保持相同的数组结构,以便我可以复制和粘贴任何需要在两个项目中实现的未来更改。 有没有办法保持记录相同而略有差异?
我在考虑这样的事情:
// in Project 1:
TExtras = record
end;
// in Project 2:
TExtras = record
XMLNode:TXMLNode;
end;
// shared - in both projects
TData1 = record
A:string;
B:integer;
C:word;
...
Extras:TExtras; // different extra fields based on project needs
end;
我可以在Project2中使用Data1.Extras.XMLNode
访问字段的其他字段中添加其他字段。不确定这是否是未来的实施。
目标是有一天将所有共享结构放入共享单元,一个维护点,不再复制和粘贴。我需要数组来保持作为简单数组(array of TData1
或TArray<TData1>
)的灵活性,因此我无法进入复杂的实现,这将限制轻松复制,排序,区分,操作数据的选项。 ..
这是正确的做法吗?有更好的想法吗?
修改:
这两个项目都使用相同的数据,所以他们都阅读相同的数据来源&#39;文件,但产生不同的最终结果。现在我有很多阵列,其中99%用于两个项目,相同功能的相同目的。 但是现在,当我在一个或另一个项目上工作时,添加新的记录字段,使用新字段的新功能,如果我不立即同步结构和新功能,那么几周后我会发生需要在项目2中执行相同的操作,我将创建具有不同名称和不同函数名称的新字段。所以,当我最终在项目之间复制一些复杂的功能时,我发现它们只是因为命名不同而不匹配。
编辑2:
从所有评论和建议中我决定采用另一种方式:在共享单元中共享通用数据结构和代码,并在项目2中创建具有额外记录字段的其他数组。我将创建这些链接到主数据的新数组数组,有:
// shared data
TData1 = record
A:string;
B:integer;
C:word;
...
end;
Data1:TArray<TData1>;
// additional in Project 2
TDataExtra = record
DataIdx:integer;// link to TData1
XMLNode:TXMLNode;
...
end;
DataExtras:TArray<TDataExtra>;
可以轻松访问每个Data1记录的XMLNode值:
fGetXMLNode(i); // where i is index in Data1 array and function will return XMLNode
我相信,我可以保留共享单元并为任何阵列添加任何额外功能,只需最少的额外工作,这比维护2数据结构和代码的成本更低。
这会是更好的解决方案吗?
答案 0 :(得分:2)
如果没有完整的上下文,很难说哪种解决方案最好/更好,但这里有一些其他方法可以实现相同的目标。
条件定义
TData1 = record
A:string;
B:integer;
C:word;
[...]
{$IFDEF NEEDXMLNODEINTDATA1}
XMLNode:TXMLNode; // different extra fields based on project needs
{$ENDIF}
end;
使用新结构
在第二个应用程序中使用不同的结构。对于大多数情况,我希望这是正确的方法。
TData1Node = record
Data1 : TData1;
XMLNode : TXMLNode;
end;
始终包含XMLNode
因为它只是一个指针,除非你的应用程序中有一些荒谬的记录,否则它几乎不会记录内存使用情况。
答案 1 :(得分:2)
Pascal没有void / Unit数据类型,你仍然可以模拟它。
编译器并不总是对它感觉良好,在某些路径中它只是没有假设/检查在某些极端情况下SizeOf(someType)
可能为零。
但是,如果你真的需要挤压Project 2中的每个最后一个字节,同时保持与Project 1共享的源代码,可以使用这个丑陋的黑客:
文件Project_1.inc
{$IFnDEF THIS_IS_PROJECT_1}
halt compilation! wrong setup!!!
{$EndIf}
{$IFDEF THIS_IS_PROJECT_2}
halt compilation! wrong setup!!!
{$EndIf}
type TDataPayload = TXMLNode;
文件Project_2.inc
{$IFnDEF THIS_IS_PROJECT_2}
halt compilation! wrong setup!!!
{$EndIf}
{$IFDEF THIS_IS_PROJECT_1}
halt compilation! wrong setup!!!
{$EndIf}
type REmpty = packed record end;
type TDataPayload = REmpty;
// after compilation - call `assert(SizeOf(TDataPayload) = 0);`
文件CommonDataType.pas
{$IfDef THIS_IS_PROJECT_1}
{$INCLUDE Project_1.inc}
{$EndIf}
{$IfDef THIS_IS_PROJECT_2}
{$INCLUDE Project_2.inc}
{$EndIf}
TData1 =
{$IFDEF THIS_IS_PROJECT_2}
packed
{$EndIf}
record
A:string;
B:integer;
C:word;
...
Payload: TDataPayLoad;
end;
话虽如此,您在项目2中通过type TXMLNode=byte
兼容性存根不能浪费单个字节的评估对我来说似乎非常可疑。这是因为:
record
而不是慢速字节压缩packed record
A:string;
每个记录中每个指针花费4(或8)个字节,然后再将{12}个字节作为StringRec
标头,然后是未知的预先分配的简单内容缓冲区字符串内容,然后两个额外的字节用于尾随#0,然后支持堆管理器中的数据结构。仍然只有type TXMLNode=boolean
存根的一个额外字节太多了??? 答案 2 :(得分:2)
简单的解决方案是保持两个项目之间共享的数据结构和相关功能,并添加包含特定于每个项目的附加数据的其他数组。 它将为使用额外的数组带来更多的工作,但会保持共享代码真正共享。
因此,与其他anwers中提出的新类或IFDef不同,链接到主数据的简单额外数组是该问题的最佳选择:
// shared main data through both projects
TData1 = record
A:string;
B:integer;
C:word;
...
end;
Data1:TArray<TData1>;
// additional in Project 2
TDataExtra = record
DataIdx:integer;// link to TData1
XMLNode:TXMLNode;
...
end;
DataExtras:TArray<TDataExtra>;
使用此解决方案,任何其他数组(如DataExtras或其他阵列的任何其他字段)都可以轻松添加,扩展,而无需更改共享代码。共享代码很容易维护,因为它只保存主要数据,而不是只有一个项目