【问题标题】:is it possible to have dynamic struct members dependent to another member in c#是否可以让动态结构成员依赖于 c# 中的另一个成员
【发布时间】:2011-08-25 03:06:08
【问题描述】:

在这种情况下,二进制文件是使用基于结构的文件格式编写的

    struct fileformat
    {
         struct mask
         {
                bool mem1present
                bool mem2present
                bool mem3present
                //5 bits unused
          }
          //member only written in file if mem1present is true
          byte mem1present
          //member only written in file if mem2present is true
          byte mem1present
          //member only written in file if mem3present is true
          byte mem1present
    }

这可以用c#实现吗

【问题讨论】:

  • 你用什么将结构写入文件?
  • 我已经尝试过编写所有内容,但如果它没有动态更改,您将无法正确编组数据。所以问题仍然存在,这是可能的还是我只是在浪费时间。我没有自己写文件我只是把数据拿出来。

标签: c# dynamic struct member


【解决方案1】:

当然——你必须在某种程度上自己实现序列化,但你可以很容易地做到这一点。

不清楚您使用的是哪种序列化 - 如果您使用 .NET 的“原始”二进制序列化,您希望覆盖 GetObjectData 仅添加序列化的相关数据,然后在受保护的构造函数采用SerializationInfoStreamingContext,从相同的数据反向填充您的结构。有关详细信息,请参阅this MSDN article

我不知道如果你使用 XML 序列化会发生什么。

如果您正在编写自己的 序列化(即您有诸如WriteToStream 之类的方法),那么您当然可以选择任何您想要的方式来表示它。

编辑:听起来您可能已经拥有需要读取的现有文件格式,但您可以定义自己的类型。很容易拥有一个包含多个成员的类或结构,并且可能一个掩码来说明设置的内容,尽管在不了解更多信息的情况下它可能不是最好的设计。虽然您可以使用显式布局来提高内存效率,但使用单独的成员可能是最简单的:

struct Foo
{
    // Bit-set to determine which fields are actually used
    private readonly byte mask;

    private readonly int value1;
    private readonly int value2;
    private readonly int value3;

    public Foo(byte mask, int value1, int value2, int value3)
    {
        this.mask = mask;
        this.value1 = value1;
        this.value2 = value2;
        this.value3 = value3;
    }
}

然后在某个地方(无论是否在数据类型中),例如:

Foo ReadFoo(Stream stream)
{
    byte mask = stream.ReadByte();
    int value1 = 0, value2 = 0, value3 = 0;
    if ((mask & 1) == 1)
    {
       // However you do that, depending on your file format
        value1 = ReadInt32FromStream(stream); 
    }
    if ((mask & 2) == 2)
    {
       // However you do that, depending on your file format
        value2 = ReadInt32FromStream(stream); 
    }
    if ((mask & 4) == 4)
    {
       // However you do that, depending on your file format
        value3 = ReadInt32FromStream(stream); 
    }
    return new Foo(mask, value1, value2, value3);
}

顺便说一句,我会认真考虑结构是否是真的最好的方法 - 考虑改用类。我很少创建自己的结构。

【讨论】:

  • 我实际上并没有使用任何序列化,我只是从数据中读取一个字节,告诉它的数据长度,然后使用 Marshall.ptrStructure 一个字节数组,以数据长度开始。你我在 c# 中实现上面的 sudo 代码时遇到了麻烦,因为它是动态的。
  • @michael:好吧,您将无法使用Marshal.PtrToStructure...您应该明确编写代码以从/向流中读取/写入字节。目前尚不清楚是您遇到问题的 IO 还是结构的基本布局。 (有什么理由它是一个结构而不是一个类,顺便说一句?)
  • 是的,我认为 Marshal.PtrToStructure 不能用于我的情况,因为动态。 IO 没问题,只要结构的基本布局是可能的,我就可以解决问题。真的没有理由。只是我想知道他们到底是怎么做到的。我猜他们也明确地实现了它。
  • @michael:在这种情况下,“他们”是谁?您需要将文件布局和内存布局的概念分开......将编辑。
  • 鳍家伙。是的,我猜这就是我完全不明白的。内存布局将尽可能完整。而在文件布局期间,他们会做一些激进的事情来节省所需的空间。谢谢乔恩。
【解决方案2】:

注意:您的示例仅显示嵌套结构类型的声明,而不是它的实例。

根据您的问题措辞,您需要一个实例成员。

struct fileformat 
{ 
     struct mask  // type declaration only
     { 
            bool mem1present 
            bool mem2present 
            bool mem3present 
            //5 bits unused 
      } 

      public mask mask;    // <-- Member instance here
} 

如果我误解了,我深表歉意。也许您的结构只是为了向我们传达文件的结构?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-28
    • 1970-01-01
    • 1970-01-01
    • 2021-01-25
    • 2020-11-25
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多