将Delphi变体记录转换为C#struct

时间:2012-02-17 16:16:50

标签: c# delphi

当我尝试从现有应用程序编写C#应用程序但在Delphi中开发时, 非常艰难,但管理了一些如何,但现在我遇到了一个问题......

Delphi代码包含以下代码:

type  
  TFruit = record
    name : string[20];
    case isRound : Boolean of // Choose how to map the next section
      True  :
        (diameter : Single);  // Maps to same storage as length
      False :
        (length   : Single;   // Maps to same storage as diameter
         width    : Single);
  end;

即。一个变体记录(里面有case语句),因此也构建了记录及其大小。 另一方面,我试图在C#struct中做同样的事情,但还没有成功,我希望有人能在这里帮助我。 所以,请告诉我是否有任何方法可以在C#中实现这一点。 提前谢谢....

3 个答案:

答案 0 :(得分:5)

您可以使用显式结构布局来复制此Delphi变体记录。但是,我不会打扰,因为您似乎不太可能希望分配到diameter并分配给length,反之亦然。 Delphi记录声明看起来像是20世纪90年代中期的Delphi编码风格。现代Delphi代码很少以这种方式编写。

我会这样做:

struct Fruit
{
    string name;
    bool isRound;
    float diameter; // only valid when isRound is true
    float length;   // only valid when isRound is false
    float width;    // only valid when isRound is false
}

更优雅的选项是具有每个struct字段属性的类。如果访问isRound的值无效,您可以安排3个浮点数的属性getter和setter引发异常。

答案 1 :(得分:1)

也许这会成功吗?

这不是复制粘贴解决方案,请注意,根据Delphi结构的声明和/或对齐方式,可能需要更改偏移量和数据大小。

[StructLayout(LayoutKind.Explicit)]
unsafe struct Fruit
{
    [FieldOffset(0)] public fixed char name[20];
    [FieldOffset(20)] public bool IsRound;
    [FieldOffset(21)] public float Diameter;
    [FieldOffset(21)] public float Length;
    [FieldOffset(25)] public float Width;
}

答案 2 :(得分:1)

这取决于你想要做什么。

如果您只想尝试制作相应的结构,请查看David Heffernan的答案。现在几乎没有理由将两个字段映射到彼此之上,除非它们真正代表相同的东西。 (比如说,单个项目或数组中的相同项目。)

如果你真的想要分享文件,你需要看看ananthonline的答案,但是它有一个问题,它足够大我不能把它放在评论中:

不仅存在Unicode问题,而且Delphi短串在C#中没有相应的结构,因此不可能简单地在其上面映射字段。

该字符串[20]实际上包含 21 字节,一个字节长度的代码,然后是20个字符的数据。您必须遵守长度代码,因为无法保证超出指定长度的内容 - 您可能会在那里找到垃圾。 (提示:如果要将记录写入磁盘,则在将新数据放入其中之前始终删除该字段。这使得在调试时更容易检查磁盘上的文件。)

因此,您需要声明两个字段并编写代码以在两端处理它。

由于你必须这样做,我会更进一步,编写代码来处理其余部分,以便根本不需要不安全的代码。