What is the StructLayoutAttribute effect on properties in C#?
Asked Answered
H

3

5

I'm defining structs to be received and sent over a communication channel between different devices and different programming languages. For that I explicitly define their layout in memory using StructLayoutAttribute (sequential, pack=1 - in case it matters).

From the documentation, I know it works when the struct contains only fields. It seems to also work for 'simple' properties (with empty get; set;). However I don't know if it's always the case.

So my question regarding StructLayoutAttribute effect on properties is divided to two:

  1. Do simple properties (again, empty get; set;) behave the same as fields?
  2. How do other properties behave, for example properties that their get is a computation over other properties? Are they ignored (since I don't see an actual data item behind them)? Do they take memory?
Heer answered 12/2, 2015 at 21:25 Comment(3)
So 3 answers and no one has given any input on how it actually behaves. I know you can't depend on it given the spec, but if you use a specific compiler you can.Senile
Why would you depend on the specific compiler when the language provides facilities to control the behavior? BTW the link I have provided contains details on how the compiler behaves.Calefactory
I ended up creating private fields and public calculated properties. Since I use code generation it was a one time change.Heer
S
3

Properties have no storage. StructLayoutAttribute does not affect them at all.

Auto-properties access a generated backing field which is subject to StructLayoutAttribute (since all fields are subject to this attribute). The order of those fields is not defined however.

Since get-properties that just compute a value have no storage they are not marshaled.

Steepen answered 12/2, 2015 at 21:50 Comment(3)
thanks. What do you mean "The order of those fields is not defined however"? Does it mean that backing fields ignore the Sequential attribute?Heer
It means that the C# compiler is free to put the generated backing fields in any order that it likes. That destroys the sequentially property that you seem to need. The CLR will obey, but csc.exe might not.Steepen
My experience on Windows with .NET Framework 4.5 is that auto-properties usually have the backing fields allocated in the order you define your properties and fields; but this is a specific scenario. I never read the specifications, but if it does not specify the order of the backing fields, then the order of those fields is completely up to the implementors of the compiler, so for example Mono may not put the fields in the same order. I'd assume that all Windows implementations follow the same rule, and would complicate the compiler to scramble the order, but don't take my words for it.Taub
C
3

According to the documentation and my tests FieldOffsetAttribute can't be applied to properties. This leaves the question of LayoutKind.Sequential. According to this article the property fields appear in the end. Basically do not use auto properties if you care about the layout. Expand them and annotate the fields. Calculated properties do not appear in the memory layout of the struct.

Calefactory answered 13/2, 2015 at 17:24 Comment(0)
R
1

Auto properties ({get; set;}) have a publicly-inaccessible backing field that is created automatically. In fact, if you use reflection to look at the fields of a class that has an auto property, you can see that there is a private field for that property. The code below prints <Bar>k__BackingField -- a weird field name, but a field name nonetheless!

I can't say I've tried StructLayoutAttribute on a property. If it works, it surely just applies that same logic to the backing field.

using System;
using System.Reflection;

namespace ConsoleApplication10
{
    class Program
    {
        static void Main(string[] args)
        {
            var fields = typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
            Console.WriteLine(fields[0].Name);
        }
    }

    class Foo
    {
        public int Bar { get; set; }
    }
}
Rudiment answered 12/2, 2015 at 21:50 Comment(4)
thanks. Will the backing fields conform to the same rules as regular fields (e.g. maintaining order on Sequential layout)? And what about non-auto properties? I assume they do not affect the layout?Heer
Like I said, I haven't tried. Even if it compiles, you will have to test to see if the attribute is actually doing anything. I would expect non-auto properties not to work. Neither the compiler nor the runtime can infer a relationship between the non-auto property and the field you have explicitly defined.Rudiment
Sorry but I really can't see how this is an answer to the question.Calefactory
@Heer the backing fields are just like regular fields, which obey all ordering rules, and you can't access without reflection, because they bare an illegal name for the language, but are legal in IL. If you define a private field next to the auto-property, and decompile it to IL, you'll see that both fields are declared the same.Taub

© 2022 - 2024 — McMap. All rights reserved.