2

As the title says I need to get int reference into byte array

class ClassFoo {
    private byte[] _data;

    public ref byte GetByteRef(int index) {
        // ...Omitted for brevity
        return ref _data[index];
    }
    public ref int GetIntRef(int index) {
        // This won't work as it returns a integer value not reference
        return ref BitConverter.ToInt32(_data, index * 4);
    } 
}

I am positive that it is possible without switching into an unsafe context. And the answer is buried somewhere in documentation below.

  1. Span
  2. MemoryMarshal
  3. Unsafe

But I failed to find it. Any help is much appreciated.

5
  • stackoverflow.com/questions/1318933/c-sharp-int-to-byte Commented Nov 20, 2023 at 0:20
  • @JonathanWood That's the other way around, and also involves a copy. Commented Nov 20, 2023 at 0:21
  • You could just ref int myInt = ref Unsafe.As<byte, int>(ref myBytes[index]). Do ensure though that after myBytes[index] there is enough space in your array to load a full size integer from (don't do out of bounds reads). It's basically the managed equivalent of int* pMyInt = (int*)(pMyBytes + index). Commented Nov 20, 2023 at 0:36
  • @FrederikHoeft You shouldn't use Unsafe, and anyway you don't need it. See my answer. Commented Nov 20, 2023 at 0:38
  • @EtiennedeMartel "You shouldn't use Unsafe" - well, that depends on the use-case and the performance you want to achieve ;) MemoryMarshal.Cast is just a wrapper around Unsafe.As(). Given that the OP just wanted to read a single element it feels weird to Cast the whole array to an int span first (though the JIT will probably optimize that away), but you'd still have the overhead of all the checks. Commented Nov 20, 2023 at 0:45

2 Answers 2

4

First, you can use MemoryMarshal.Cast to convert a byte span to an int span. Since arrays are implicitly convertible to spans, you can just plug the array in there:

var intSpan = MemoryMarshal.Cast<byte, int>(_data);

And then you get a ref to the span's index of your choice:

return ref intSpan[index];

Or, in one go:

return ref MemoryMarshal.Cast<byte, int>(_data)[index];

No pointer required.

Sign up to request clarification or add additional context in comments.

2 Comments

It works but the bytes are in reverse order. So, the .NET stores the Int32 in 'Little Endian', I guess... Nevertheless I can work with that.
@JanTajovsky you may want to take a look at the BinaryPrimitives class in System.Buffers.Binary if you need network byte order ;)
0

To my knowledge, you can't directly use a reference to an int for a byte array in old .Net Framework versions. Since arrays are in C# are reference types and the reference itself is already used to reference to the array(like an object reference). The only way is you can use the unsafe keyword and pointers to achieve a similar.

3 Comments

That was true in the ancient times of .NET Framework, but we have spans now.
Aren't spans underneath use unsafe ?
What they use for their implementation is irrelevant, you can use spans without the unsafe keyword.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.