Reference array in C #?

I have an array of bytes:

byte[] alldata = new byte[1024]; 

then I need to convert this data to UInt32 :

 UInt32[] block32 = new UInt32[(int)Math.Ceiling((double)alldata.Length / 4)]; Buffer.BlockCopy(alldata, 0, block32, 0, alldata.Length); 

then I need to convert block32 an array byte .

The question is, can a block32 array be a 32-bit reference array of my byte array to avoid converting to UInt32 and vice versa?

+6
source share
3 answers

Your question is not entirely clear, but the reference is only to one object, and the array object "knows" its real type ... you cannot just consider uint[] as if it were byte[] or vice versa.

Now what you could do is hide it behind another object. You can have one byte array that is shared between ByteArrayView and UInt32ArrayView , where these classes know how to access one basic byte array. You must write these classes yourself - I do not believe that they exist anywhere in the existing structure.

You could create an abstract class or interface that these disparate classes would implement, for example,

 class ByteArrayView : IArrayView<byte> class UInt32ArrayView : IArrayView<uint> 

(Or just implement IList<T> accordingly, of course ...)

+12
source

I reworked the answer I found here from Omer Mor . It basically uses unsafe code to temporarily change the type that the array considers.

On the plus side, you donโ€™t need to rewrite any other code to use unsafe pointers or wrapper classes. On the other hand, this is not only unsafe code, but also an unpleasant unsafe code that is incompatible with the type system.

 static class ArrayCaster { [StructLayout(LayoutKind.Explicit)] private struct Union { [FieldOffset(0)] public Byte[] Bytes; [FieldOffset(0)] public UInt32[] UInt32s; } static unsafe int UInt32Id { get { fixed (UInt32* pUints = new UInt32[1]) { var pBytes = (Byte*)pUints; return *(int*)(pBytes - 8); } } } static unsafe void SetSizeAndId( byte[] bytes, int newSize, int newId, out int oldSize, out int oldId) { fixed (Byte* pBytes = bytes) { int* size = (int*)(pBytes - 4); oldSize = *size; *size = newSize; int* id = (int*)(pBytes - 8); oldId = *id; *id = newId; } } public static void WithBytesAsUInt32s( Byte[] bytes, Action<UInt32[]> withUints) { if (bytes.Length % sizeof(UInt32) != 0) throw new ArgumentException(); Union u = new Union { Bytes = bytes }; int origSize, origId; SetSizeAndId(bytes, bytes.Length / sizeof(UInt32), UInt32Id, out origSize, out origId); try { withUints(u.UInt32s); } finally { SetSizeAndId(bytes, origSize, origId, out origSize, out origId); } } } 

In your code:

 byte allData = new byte[1024]; ArrayCaster.WithBytesAsUInt32s(allData, uintArray => Encrypt(unitArray)); 

Edit: in the event that your encryption / decryption methods take an explicit length, as well as a UInt32 array, you can completely cut unsafe code; just using Union works fine, except that (a) the debugger inspector is confused and (b) the length is not updated. If you can say that your methods use only a quarter of the array, you are golden.

+1
source

As you mentioned, you will use uint[] for encryption.

For some reason you copy arrays using BlockCopy . But you want to access byte[] as uint[] without transforming or casting the whole array.

Then something is missing? Is there anything in C # for this?

Think one more hour, I think, for what you need, there should be an indexer .

Here is the code. It's simple.

 public partial class UIntIndexer { static int ComputeElementCount(int size, int bytesCount) { var r=~0; return Math.DivRem(bytesCount, size, out r)+(r>0?1:0); } static int ComputeIndex(int index) { return sizeof(uint)*index; } public UIntIndexer(byte[] array) { m_Length=ComputeElementCount(sizeof(uint), (m_Array=array).Length); } public uint this[int index] { set { var startIndex=ComputeIndex(index); var bytes=BitConverter.GetBytes(value); var count=m_Length>1+index?sizeof(uint):m_Array.Length-startIndex; Buffer.BlockCopy(bytes, 0, m_Array, startIndex, count); } get { var startIndex=ComputeIndex(index); if(m_Length>1+index) return BitConverter.ToUInt32(m_Array, startIndex); else { var bytes=new byte[sizeof(uint)]; Buffer.BlockCopy(m_Array, startIndex, bytes, 0, m_Array.Length-startIndex); return BitConverter.ToUInt32(bytes, 0); } } } public int Length { get { return m_Length; } } byte[] m_Array; int m_Length; } 

If there is a thread safety issue, you may need to synchronize the source array. Below is the code for testing:

 var alldata=new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; var block32=new byte[alldata.Length]; var uintIndexer=new UIntIndexer(block32); Buffer.BlockCopy(alldata, 0, block32, 0, alldata.Length); Debug.Print("uintIndexer.Length={0}", uintIndexer.Length); for(var i=uintIndexer.Length; i-->0; ) Debug.Print("uintIndexer[{0}]={1}", i, uintIndexer[i]); 
0
source

All Articles