0

There are many questions that ask how to get a subset of an array on this site, however no one has successfully gotten an answer on how to write to the array as if it were byte[].

byte[] bigTargetBytes = new byte[10000];

byte[] twentyBytes = sha256.ComputeHash(sourcebytes);  // size is 20 bytes, 
// how do I append this to the existing array without copying, using Linq, etc?

What I don't want to do is have two arrays and do a copy between them, since that is time intensive proportional to the length of the array (and my arrays are long)

makerofthings7
  • 60,103
  • 53
  • 215
  • 448

2 Answers2

3

I'm afraid you will have to make a copy either way. I suggest you to use the Buffer.BlockCopy() method, which is the fastest.

e_ne
  • 8,340
  • 32
  • 43
1

It's not exactly clear what you want, but I'm guessing you want a "view" onto an array of bytes. In .Net 4.5, you can do this with ArraySegment<T>:

var a = new byte[100];
var s = new ArraySegment<Byte>(a, 9, 90);

((IList<Byte>)s)[0] = 10;
Console.WriteLine(a[9]);  // writes "10"

So, your Write90Bytes method could return an ArraySegment<Byte> and then you could operate on that as a view into the underlying array, which would avoid the copy. Note, however, that ArraySegment<T> is a System.ValueType, which means casting it to IList<T> will incur a boxing penalty.

If performance is critical and you need to avoid copying, you might also consider using pointers in an unsafe context, which means your Write90Bytes method could return a Byte* and you could then index into the array that way.

EDIT: now that I see your edit, you can't just return a value from a function "into" the memory location of an array. You'd need to pass the original array as an argument.

EDIT 2: you can't do what you are asking. The ComputeHash function returns an array which it itself allocates. The only way you could do what you want is if ComputeHash took the array as a parameter. Consider:

// previously defined...
byte[] bigTargetBytes = new byte[10000];      

// This method doesn't really exist, but if it did it would look like this
sha256.ComputeHash(sourcebytes, bigTargetBytes, offset); 

Although in .Net there are specific restrictions on memory allocation due to it being a managed runtime, this is a common pattern in any programming language. In C/C++ development, there is a protocol used where either you pass in a pre-allocated array with an offset and maxlength to write to, or you allow the function to return an allocated memory which you are then given the responsibility to free (unless you are being called back from a framework). You can't just return a value into an existing buffer.

Do note however, that just copying 20 bytes from a GC array allocated by the ComputeHash value is a very trivial operation, which the runtime handles very efficiently. Unless you are very sensitive to microsecond level pauses from time to time, you won't notice the difference between the actual copy and your hypothetical implementation.

codekaizen
  • 26,990
  • 7
  • 84
  • 140