2016-07-20 1 views
0

J'essaie de créer une structure de type union avec le champ byte []. Donc déclaration de type suivante provoque une erreur dans l'exécution:Champ de matrice de stockage dans une structure de type union

[StructLayout(LayoutKind.Explicit)] 
public struct Int64ByteArr 
{ 
    [FieldOffset(0)] 
    public UInt64 u64; 
    [FieldOffset(0)] 
    public Int64 s64; 
    [FieldOffset(0), MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]   
    public byte[] bytes; 
} 

lorsque vous appelez une fonction qui utilise la variable de ce type, les causes programme exception avec cette description:

Необработанное исключение типа "System.TypeLoadException" в System.Windows.Forms.dll Дополнительные сведения: Не удалось загрузить тип "Int64ByteArr" из сборки "ChalengeCalc, version = 1.0.0.0, Culture = neutral, PublicKeyToken = null", так как он содержит поле объекта со смещением 0, которое н еверно выровнено или перекрыто полем, не представляющим объект.

Traduction

à l'anglais: exception non gérée de type "System.TypeLoadException" dans System.Windows.Forms.dll) Informations complémentaires: Impossible de charger le type "Int64ByteArr" de « ChalengeCalc, Version = 1.0.0.0, Culture = neutral , PublicKeyToken = null » Assembly car il contient des champs de l'objet avec oaffset 0, ce qui est mal aligné de déborder par le champ qui ne présentant pas un objet

J'essaie aussi cette variante:

[StructLayout(LayoutKind.Sequential)] 
public struct ByteArr8 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 
    public byte[] bytes; 
    public Byte this[int idx] 
    { 
     get 
     { 
      if (idx < 0 || idx > 7) return 0; 
      return bytes[idx]; 
     } 
     set 
     { 
      if (idx < 0 || idx > 7) return; 
      bytes[idx] = value; 
     } 
    } 
} 
[StructLayout(LayoutKind.Explicit)] 
public struct Int64ByteArr 
{ 
    [FieldOffset(0)] 
    public UInt64 u64; 
    [FieldOffset(0)] 
    public Int64 s64; 
    [FieldOffset(0)] 
    public ByteArr8 bytes; 
} 

il se bloque avec la même exception. Donc, il y a une question: "comment?"

+0

Copie possible de [structures C# pinvoke avec union et tableaux] (http://stackoverflow.com/questions/20274284/c-sharp-pinvoke-structs-with-union-and-arrays) –

+2

Vous ne pouvez pas superposer une référence à un type de référence comme byte [] avec une valeur de type de valeur. Cela vissera le garbage collector. Vous devrez utiliser un tampon de taille fixe à la place. Puisque le tableau a la même taille que Int64, une autre solution de contournement très simple consiste à utiliser BitConverter.GetBytes() pour lire les valeurs d'octets. –

Répondre

1

Dans votre cas, vous pouvez rassembler le champ de tableau d'octets seulement et fournir getters/setters pour les autres:

[StructLayout(LayoutKind.Sequential)] 
struct Int64ByteArr 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 
    public byte[] bytes; 
    public UInt64 u64 
    { 
     get { return BitConverter.ToUInt64(bytes, 0); } 
     set { bytes = BitConverter.GetBytes(value); } 
    } 
    public Int64 s64 
    { 
     get { return BitConverter.ToInt64(bytes, 0); } 
     set { bytes = BitConverter.GetBytes(value); } 
    } 
} 

Note: inspirée par le commentaire de David Heffernan à this question.

En général, vous devriez utiliser le marshaling personnalisé, je crois.