7

Is there a way to get the length of a fixed size buffer?

Something like:

public struct MyStruct
{
    public unsafe fixed byte buffer[100];

    public int foo()
    {
        return sizeof(buffer); // Compile error.
    }
}

Is there any way to accomplish something like this?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
andresantacruz
  • 1,676
  • 10
  • 17
  • 2
    Why don't you define a constant like const int BUFFER_SIZE = 100, then use buffer[BUFFER_SIZE]. This runs quicker size the assignment is done by the compiler. – jdweng May 09 '16 at 17:15
  • Because that would add some unwanted verbosity to my structs. My code would have a lot of structs like that. Any thoughts? Thanks. – andresantacruz May 09 '16 at 17:18
  • 4
    It is a lot less code than to put a method foo in each structure. – jdweng May 09 '16 at 17:37
  • 2
    But I wasn't going to create that foo method, I just wrote to clarify the things and concepts :( – andresantacruz May 09 '16 at 17:38

3 Answers3

4

Well like in C++, you have to keep size of built-in arrays. Same applies for fixed buffers in C#. This type is comparable to inline_array. This gives you benefits such as static code checking. They are a bit of a pain to work with as they aren't C#'s first class feature. So probably the best solution is to keep size as a part of struct. You will probably just have to deal with it or use a collection/C#'s System.Array. Maybe another solution would be to create fixed buffer as a seperate struct and then make it part of another stucts with other data.

Community
  • 1
  • 1
fsacer
  • 1,382
  • 1
  • 15
  • 23
  • Okay, considering this is the closer answer 'll accept. Unfortunatelly c# is showing itself very limited when deeper interop comes to play :/ – andresantacruz May 09 '16 at 18:41
  • "in C++, you have to keep size of built-in arrays" just isn't true. `(sizeof array)/(sizeof *array)` works great on built-in arrays, including struct/class data members with array type. Or you can use inference of non-type template parameters. You linked to a discussion on finding the size of the dynamic memory range a pointer points to, which is not at all what is going on in the C# code in the question. – Ben Voigt Jan 14 '22 at 20:19
0

Well, I'm answering like 6 years late but I did this. Apparently there's a property that contains the length of the fixed buffer! Here's a simple method to get it. You need to pass the MyStruct type and the name of the field:

    public static int GetFixedBufferSize(Type type, string field)
    {
        FieldInfo fi = type.GetField(field);
        object[] attrs = fi.GetCustomAttributes(typeof(FixedBufferAttribute), false);
        if (attribs != null && attribs.Length != 0)
        {
            FixedBufferAttribute attr = (FixedBufferAttribute)attribs[0];
            Console.WriteLine($"{attr.ElementType.Name} {field}[{attr.Length}]");
            return attr.Length;
        };

        throw new Exception("Not a FixedBuffer");
    }

Hopefully this works for you, I tried it with your example and it worked!

Gaspa79
  • 5,488
  • 4
  • 40
  • 63
  • 1
    Does this depend on reflection? You're asking for a field according to its name as a runtime-variable string? Surely that's not fast, so it's not something you'd want to use in normal code if you're using an `unsafe fixed` array for performance reasons. – Peter Cordes Jan 14 '22 at 17:46
-4

That's an array; you can just use .Length.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • fixed size buffers isn't an array. Length is a property of System.Array, therefore I can't access that :( – andresantacruz May 09 '16 at 17:11
  • Maybe @MartinCostello, could you show me how I could use Marshal.SizeOf in a fixed buffer? Thanks. – andresantacruz May 09 '16 at 17:14
  • You could try these: `return Marshal.SizeOf(this);` `return Marshal.SizeOf(typeof(MyStruct));` `return Marshal.SizeOf(buffer);` – Martin Costello May 09 '16 at 17:16
  • None of that works in my case @MartinCostello. MyStruct would contain another types, SizeOf(typeof(MyStruct)) will return the marshal size of the entire struct and SizeOf(buffer) don't compile. SizeOf expects a Type. – andresantacruz May 09 '16 at 17:20
  • `buffer` is a field, which is an object. Does the code even compile if you remove the `foo()` method? I think your field declaration is wrong. – Martin Costello May 09 '16 at 17:22
  • 2
    @MartinCostello: No; it's just that `fixed` is weird. I'm not sure if this is possible at all (!). Play with http://tryroslyn.azurewebsites.net/#f:s/K4Zwlgdg5gBAygTxAFwKYFsDcAobAHYAIwBswBjGFAJ2DORgFkE5ka7sBvbGHmAk8jGAQQAQwBmqGOLAAPVABMYhBGmXBxkqgG0AjAAZ9AXRzde/UhWFjJMSPXEB7RwAoAlGZ5dePmFVTIwFQQ6pqoVAB0ADKo0MgAFjg+AL7YqUA=== – SLaks May 09 '16 at 17:23
  • Maybe try using `[MarshalAs]`, rather than `fixed`. Then you won't need unsafe code. https://github.com/martincostello/sqllocaldb/blob/master/src/SqlLocalDb/LocalDbVersionInfo.cs#L48-L49 – Martin Costello May 09 '16 at 17:24