2014-01-03 3 views
4

Есть два способа определить эту структуру, которую я хочу передать в качестве аргумента функции pinvoke. Я хотел бы знать, в чем разница между 2В чем разница между этими двумя структурами

[StructLayout(LayoutKind.Sequential)] 
public struct Rect { 
    public int left; 
    public int top; 
    public int right; 
    public int bottom; 
} 

[StructLayout(LayoutKind.Explicit)] 
public struct Rect { 
    [FieldOffset(0)] public int left; 
    [FieldOffset(4)] public int top; 
    [FieldOffset(8)] public int right; 
    [FieldOffset(12)] public int bottom; 
} 

Из определений макетов я нашел here, и не должны выглядеть так же в памяти? Любые преимущества одного над другим?

+1

Первый - нормальный, а второй нет. –

ответ

5

Из определений макетов, которые я нашел здесь, не должны оба выглядеть одинаково в памяти?

Да, они будут выглядеть одинаково в памяти.

Любые преимущества одного над другим?

Быстрее выписывать и читать легче.


Использование FieldOffset, конечно, полезный инструмент; это не так, как всегда бесполезно, но если вы просто так использовали его, чтобы явно выложить поля в усадьбе, в которых они будут выложены по умолчанию, тогда это бесполезно. Если вы используете его для размещения полей в усадьбе, отличных от их значения по умолчанию (например, с перекрытием, добавлением пробельного пространства, имеющим базовое представление, в другом порядке, чем порядок объявления и т. Д.), Тогда это не бесполезно ,

+0

Я согласен, если вы не делаете ничего такого, как переупорядочение, промежуточные значения с заполнением и т. Д. Тогда первая версия проще, будет более ремонтопригодной и приведет к меньшим ошибкам. Что происходит, когда вы хотите добавить поле (теперь вы должны делать математику и можете испортить). –

1

Теоретически эти два являются точно такими же. Обычно вы используете явный макет, когда вы взаимодействуете с не управляемым кодом. Это может быть важно, потому что в будущем «int» может не иметь 32 бит в нем - это означает, что последовательный макет больше не может быть применим. Надеюсь, это поможет!

Редактировать

Еще одна мысль, если вы отображения структуры .NET неуправляемый союза или с использованием различных типов в .NET, чем в неуправляемом коде, это будет очень полезно.

Второй Редактировать

Другие отметили, что MS не будет «никогда» изменить размер в междунар. Я могу согласиться с тем, что это будет разрушительное изменение, и поэтому сильно маловероятно. Тем не менее, явное описание структуры, когда маршалинг значений между .NET и неуправляемым кодом все еще может быть хорошей идеей. Это особенно актуально, если в будущем возможно изменение неуправляемой структуры/макета.

+0

'в будущем« int »может не иметь 32 бита в нем. Это, безусловно, не так. В C# 'int' это просто псевдоним для' System.Int32'. Он всегда будет 32 бита, в отличие от, скажем, C++, в котором определяется только минимальный размер. – Servy

+0

@Servy Я хотел бы думать, что вы правы, но возможно, что Microsoft может в какой-то момент изменить компилятор (не без предупреждения, конечно). В этот момент все эти значения нужно будет переустановить, используя явный макет. –

+2

@ drew_w: Нет; Microsoft не изменит размер 'int'. Это было бы одним из самых больших разрушительных изменений, которые можно себе представить. – SLaks

0

Я не думаю, что для этой проблемы существует реальная версия макета. Вторая версия с ExplicitLayoutKind позволяет изменять порядок элементов структуры, поскольку вы указываете свою позицию в памяти с помощью fieldoffest. Вторая версия, на мой взгляд, проще расширить.

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