2013-08-12 2 views
3

Это оригинальное заявление:поля только для чтения массива в небезопасных структурах

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

Я хотел бы сделать struct только для чтения, но я не знаю, как я должен написать геттер для массива , Единственное решение, которое я мог бы выяснить, является добытчик метод:

[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]; } } 
}; 

Можно ли написать геттер свойство для Ь вместо метода геттер ?

=== UPDATE ===

Я также хотел бы, чтобы обработать случай, когда есть более одного поля массива. Например:

[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]; } } 
}; 

Можно ли написать геттер свойства для Б и вместо того, чтобы геттер методы? Я хотел бы написать y.B[i] и y.C[i] вместо y.B(i) и y.C(i).

+0

Вы всегда должны использовать объявление, подобное этому, для неуправляемого взаимодействия с кодом. В этот момент член структуры, доступный только для чтения, больше ничего не значит. Язык, с которым вы взаимодействуете, требует объявления таким образом, возможно, с * const *. –

+0

@HansPassant Да, мне нужно это для кода interop. У меня есть байт * от сторонней неуправляемой библиотеки, и после добавления смещения я передал его указателям на похожие небезопасные структуры. Я просто хочу (1) остановить пользователей моего кода, перезаписывая исходные неуправляемые данные, и (2) изменить некоторые поля внутри получателя. Поэтому я сделал каждое поле частным и добавил геттеры. – kol

+0

Никогда не подвергайте ненадежные структуры клиентскому коду. Это небезопасно, и никто не любит включать этот вариант. –

ответ

3

Вы можете использовать свойство indexer для доступа к массиву с определенным индексом. К сожалению, она должна быть определена на самой структуры, а не B, но это должно обеспечить то, что вы ищете:

[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; 
     } 
    } 
}; 
+2

примечание: может быть упрощено до ' fixed (byte * ptr = b) {return ptr [i]; } '- но по существу, yup: this –

+0

+1 ОК, но то, что я хотел бы индексировать, не сам X, а его поле b. Предположим, что у меня есть другое поле массива, c. Я хотел бы индексировать оба b, как x.B [i] и c, как x.C [i], где x имеет тип X. – kol

+0

@Chris Я продлил вопрос, включив случай, когда есть несколько полей массива. Спасибо за помощь! – kol

1

Я нашел решение, которое основано на идее 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; } } 
}; 

 Смежные вопросы

  • Нет связанных вопросов^_^