Couler des structures explicitement aménagées

Disons que j’ai cette structure,

[StructLayout(LayoutKind.Explicit)] public struct Chapter4Time { [FieldOffset(0)] public UInt16 Unused; [FieldOffset(2)] public UInt16 TimeHigh; [FieldOffset(4)] public UInt16 TimeLow; [FieldOffset(6)] public UInt16 MicroSeconds; } 

et cette structure.

 [StructLayout(LayoutKind.Explicit)] public struct IEEE_1588Time { [FieldOffset(0)] public UInt32 NanoSeconds; [FieldOffset(4)] public UInt32 Seconds; } 

Comment pourrais-je convertir d’une structure à l’autre?

Deux options ici:

Pas de code dangereux, mais une structure de structure explicite

(Notez que bien que cela ne soit pas dangereux en ce qui concerne le compilateur C #, certains frameworks peuvent toujours le refuser – voir le commentaire de Marc Gravell.)

Vous pouvez utiliser un type d’union, qui est simplement une autre structure avec deux champs, tous deux définis explicitement au même emplacement. Voici un exemple complet utilisant vos structures:

 using System; using System.Runtime.InteropServices; [StructLayout(LayoutKind.Explicit)] public struct Chapter4Time { [FieldOffset(0)] public UInt16 Unused; [FieldOffset(2)] public UInt16 TimeHigh; [FieldOffset(4)] public UInt16 TimeLow; [FieldOffset(6)] public UInt16 MicroSeconds; } [StructLayout(LayoutKind.Explicit)] public struct IEEE_1588Time { [FieldOffset(0)] public UInt32 NanoSeconds; [FieldOffset(4)] public UInt32 Seconds; } [StructLayout(LayoutKind.Explicit)] public struct TimeUnion { [FieldOffset(0)] public Chapter4Time Chapter4Time; [FieldOffset(0)] public IEEE_1588Time IEEE_1588Time; } class Test { static void Main() { var ch4 = new Chapter4Time { TimeLow = 100, MicroSeconds = 50 }; var union = new TimeUnion { Chapter4Time = ch4 }; Console.WriteLine(union.IEEE_1588Time.Seconds); } } 

Code non sécurisé, pointeurs de casting

Si vous pouvez utiliser du code non sécurisé, une alternative au type d’union Chapter4Time* à IEEE_1588Time* un pointeur de type Chapter4Time* en IEEE_1588Time* :

 class Test { unsafe static void Main() { var ch4 = new Chapter4Time { TimeLow = 100, MicroSeconds = 50 }; var ieee1588 = *((IEEE_1588Time*) &ch4); Console.WriteLine(ieee1588.Seconds); } } 

Personnellement, j’éviterais si possible de faire tout cela, mais si vous * voulez vraiment le faire, ce sont probablement les approches les plus simples.