Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are efficient fixed-size arrays possible without using unsafe code in .NET?

Tags:

arrays

c#

unsafe

Is there a good way of implementing a fixed-size array in .NET that does not require unsafe code?

My goal is to create a value type which represents a fixed-size array which can be embedded (included as a member) in other types - i.e. I'm specifically hoping to avoid creating an array as a seperate object to the type which declares it.

I realize that .NET's implementation of arrays is superb and supported at CLR/CIL level - and don't really want to debate whether or not to just use arrays... the exploration here is to whether or not a safe, fixed-size, value type implementation is possible with almost as good efficiency.

like image 539
Mark Avatar asked Nov 03 '10 03:11

Mark


2 Answers

The objective is to be able to have a fixed-size value-type array which can be used as a private member on other types. Consider a custom dictionary or linked-list implementation... the number of heap allocations can be reduced if each bucket/node is flattened to contain it's own, fixed-size array.

Making your array a value type does not necessarily mean it's going to be stored on the stack. In fact, if it's a value type embedded within a reference type, it's most likely going to be stored on the heap with the reference type, and not on the stack.

So making it a value type will not reduce heap allocations at all.

More info here: Link

like image 177
Robert Harvey Avatar answered Sep 27 '22 16:09

Robert Harvey


After some research using reflector, it turns out that the following represents an acceptable (performance-wise) solution, since C# compiles a switch statement against integers into a CIL switch statement, which is implemented as a jump-list... that is - the getter executes in about 11 CIL instructions, which it fine.

 public struct EmbeddedArray<T>
    {
        private T _element0;
        private T _element1;
        private T _element2;

        public int Length { get { return 3; } }


        public T this[int index]
        {
            get
            {
                switch (index)
                {
                    case 0:
                        return _element0;
                    case 1:
                        return _element1;
                    case 2:
                        return _element2;
                }
                throw new ArgumentOutOfRangeException("index");

            }
        }
    }

Please see Hans' comment below. It turns out that this is not as performant as I'd hoped... once the CIL is compiled to native machine code, the measured performance is far off what a .NET array will yield.

like image 40
Mark Avatar answered Sep 27 '22 18:09

Mark