3

This is the original declaration:

[StructLayout(LayoutKind.Explicit, Size = 16)] public unsafe struct X { [FieldOffset(0)] public ushort a; [FieldOffset(2)] public fixed byte b[14]; }; 

I would like to make the struct read-only, but I don't know how I should write a getter for the array. The only solution I could figure out is a getter method:

[StructLayout(LayoutKind.Explicit, Size = 16)] public unsafe struct X { [FieldOffset(0)] private ushort a; [FieldOffset(2)] private fixed byte b[14]; public ushort A { get { return a; } } public byte B(int i) { fixed (byte* p = b) { return p[i]; } } }; 

Is it possible to write a getter property for b instead of a getter method?

=== UPDATE ===

I would also like to handle the case when there are more than one array fields. For example:

[StructLayout(LayoutKind.Explicit, Size = 24)] public unsafe struct Y { [FieldOffset(0)] private ushort a; [FieldOffset(2)] private fixed byte b[14]; [FieldOffset(16)] private fixed byte c[8]; public ushort A { get { return a; } } public byte B(int i) { fixed (byte* p = b) { return p[i]; } } public byte C(int i) { fixed (byte* p = c) { return p[i]; } } }; 

Is it possible to write a getter properties for b and c instead of getter methods? I would like to write y.B[i] and y.C[i] instead of y.B(i) and y.C(i).

4
  • You should only ever use a declaration like this for unmanaged code interop. At that point, having a structure member read-only just doesn't mean anything anymore. The language you interop with needs to declare it that way, maybe with const. Commented Aug 12, 2013 at 13:08
  • @HansPassant Yes, I need this for interop code. I have a byte* from 3rd party unmanaged lib and after adding an offset I cast it to pointers to similar unsafe structures. I just want (1) to stop the users of my code overwriting the original unmanaged data, and (2) to modify some fields inside the getter. So I made every field private and added getters. Commented Aug 12, 2013 at 13:25
  • Never expose unsafe structures to client code. It is unsafe and nobody likes having to turn on the option. Commented Aug 12, 2013 at 13:27
  • @HansPassant I needed to do this to achieve the prescribed performance. Actually this question is related to this one: stackoverflow.com/questions/17549123/… Commented Aug 12, 2013 at 13:34

2 Answers 2

3

You can use an indexer propertie to access the array at a particular index. Unfortunately it needs to be defined on the struct itself rather than B, but this should provide what you're looking for:

[StructLayout(LayoutKind.Explicit, Size = 16)] public unsafe struct X { [FieldOffset(0)] private ushort a; [FieldOffset(2)] private fixed byte b[14]; public ushort A { get { return a; } } public byte this [int i] { get { byte b1; fixed (byte* b2 = b) { b1 = b2[i]; } return b1; } } }; 
Sign up to request clarification or add additional context in comments.

4 Comments

note: can be simplified to fixed (byte* ptr = b) { return ptr[i]; } - but essentially, yup: this
+1 OK, but what I would like to index is not X itself, but its field b. Suppose that I have another array field, c. I would like to index both b, like x.B[i], and c, like x.C[i], where x is of type X.
@Chris I extended the question to include the case when there are multiple array fields. Thank you for your help!
@MarcGravell Thanks for the suggestion, I simplified the code in the question.
1

I found a solution, which is based on the idea of indexed properties:

[StructLayout(LayoutKind.Explicit, Size = 14)] public struct YB { [FieldOffset(0)] private fixed byte b[14]; public byte this[int i] { get { fixed (byte* p = b) { return p[i]; } } } } [StructLayout(LayoutKind.Explicit, Size = 8)] public struct YC { [FieldOffset(0)] private fixed byte c[8]; public byte this[int i] { get { fixed (byte* p = c) { return p[i]; } } } } [StructLayout(LayoutKind.Explicit, Size = 24)] public unsafe struct Y { [FieldOffset(0)] private ushort a; [FieldOffset(2)] private YB b; [FieldOffset(16)] private YC c; public ushort A { get { return a; } } public YB B { get { return b; } } public YC C { get { return c; } } }; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.