2010-08-09 5 views
0

Je crée un tableau comme ci-dessous:Lors de la création d'un tableau dans une structure, cette structure contient-elle directement la valeur du tableau ou la référence de mémoire de ce tableau?

public struct Smb_Parameters 
     { 
      public byte WordCount; 
      public ushort[] Words; 
     } 

Alors que j'assigner les valeurs comme ci-dessous:

Smb_Parameters smbParameter = new Smb_Parameters(); 
smbParameter.WordCount = 0; 
string words= "NT LM 0.12"; 
smbParameter.Words = Encoding.ASCII.GetBytes(name); 

Dans l'affectation ci-dessus smbParameter.WordCount contient la valeur 0 mais ne smbParameter.Words contient directement les valeurs (Arry de byteS) ou une référence mémoire à l'emplacement qui contient les valeurs?

Edit 1:

Je veux envoyer un paquet au serveur. Pour cela, je dois convertir objet Smb_Parameters à un tableau en utilisant le code suivant:

int len = Marshal.SizeOf(Smb_Parameters); 
byte[] arr = new byte[len]; 
IntPtr ptr = Marshal.AllocHGlobal(len); 
Marshal.StructureToPtr(Smb_Parameters, ptr, true); 
Marshal.Copy(ptr, arr, 0, len); 
Marshal.FreeHGlobal(ptr); 
+1

Voir la réponse de Jon. – NullUserException

+0

Juste un détail, mais je ferais que 'ushort WordCount' et' byte [] Words'. –

Répondre

3

Sauf si vous utilisez fixed-size buffers dans le code dangereux, ce sera une référence. En général, peu importe si une variable est contenue dans une structure ou une classe - ou bien s'il s'agit d'une variable locale: le type de la variable décide si la valeur est une référence ou si elle contient directement les données. Mis à part les tampons de taille fixe que j'ai mentionnés, les tableaux sont toujours des types de référence dans .NET.

(Il y a aussi stackalloc qui ressemble un peu à une allocation de tableau - il alloue un bloc de mémoire sur la pile Encore une fois, ce ne doit être utilisé dans le code dangereux, et très rarement rencontré dans mon expérience..)

Dans l'exemple que vous avez donné (convenablement ajusté pour le faire compiler) Words serait certainement une référence. En particulier, si vous affectez la valeur pour faire référence à un tableau particulier, puis modifiez le contenu de ce tableau, les modifications seront visibles via la variable de la structure. .

(je vous recommande fortement que vous ne pas avoir des champs publics ou des types de valeur mutables Espérons que cela était juste pour le plaisir d'un exemple bien :)

EDIT: Pour répondre à la question mise à jour , n'envoyez pas de données comme cela. C'est une manière horriblement fragile de sérialiser n'importe quoi. Il y a plusieurs meilleures options:

  • Utilisez sérialisation binaire .NET (aussi un peu fragile en termes de versioning, et non multiplateformes)
  • Utilisez sérialisation XML (probablement exagéré dans ce cas)
  • Utilisez un framework de sérialisation tiers (par exemple Thrift ou Protocol Buffers)
  • Sérialisation manuelle avec une méthode "ToByteArray" ou "WriteToStream" dans votre classe qui sérialise chaque valeur explicitement. Vous pouvez utiliser BinaryWriter pour cela.
+0

@Jon Skeet, merci Jon. Mais je ne serai pas en mesure d'accéder aux champs (letz Say WordCount via smbParameter si WordCount n'est pas public.Est-il un autre moyen – Simsons

+1

@Subhen: Oui - fournir un constructeur qui prend les valeurs pertinentes, rendre les champs privés, et fournir au public propriétés en lecture seule.Cependant, je déconseille de mettre un tableau dans une structure pour commencer (si vous fournissez un accès au monde extérieur) car les tableaux non vides sont toujours modifiables. Y a-t-il une raison pour laquelle vous voulez que ce soit une structure plutôt qu'une classe? –

+0

@Jon Skeet, je n'utilisais pas Struct pour savoir comment obtenir la taille de l'objet de classe. Pour Struct je le fais par Marshal.SizeOf (myStruct); Le Marshal.SizeOf ne fonctionne pas avec l'objet de classe – Simsons

Questions connexes