Reputation: 2754
What is the best way to copy a string into a raw memory buffer in C#?
Note that I already know how and when to use String and StringBuilder, so don't suggest that ;) - I'm going to need some text processing & rendering code and currently it looks like a memory buffer is both easier to code and more performant, as long as I can get the data into it. (I'm thinking of B-tree editor buffers and memory mapped files, something which doesn't map well into managed C# objects but is easily coded with pointers.)
Things I already considered:
C++/CLI can do the thing, there is PtrToStringChars in vcclr.h which can then be passed to memcpy, but I'm usually preferring only having one assembly and merging the IL from multiple languages is something I like to avoid. Any way to rewrite that function in C#?
System.Runtime.InteropServices.Marshal has functions which copy the string, but only to a newly allocated buffer. Couldn't find any function to copy into an existing buffer.
I could use String.CopyTo and use an array instead of a memory buffer, but then I need to pin that buffer a lot (or keep it pinned all the time) which is going to be bad for GC. (By using a memory buffer in the first place I can allocate it outside the managed heap so it doesn't mess with the GC.)
If there's a way to pin or copy a StringBuilder then that would probably work too. My text usually comes from either a file or a StringBuilder, so if I can already move it into the memory buffer at that point it never needs to go through a String instance. (Note that going from StringBuilder to String doesn't matter for performance because this is optimized to not make a copy if you stop using the StringBuilder afterwards.)
Can I generate IL which pins a String or StringBuilder? Then instead of writing the copy-function in C# I could generate a DynamicMethod by emitting the required IL. Just now thought of this while writing the question, so I might just try to disassembly the C++/CLI way and reproduce the IL.
Upvotes: 3
Views: 1768
Reputation: 108810
enable unsafe code(Somewhere in the project options), then use:
unsafe
{
fixed(char* pc = myString)
{
}
}
and then just use low level memory copies.
Upvotes: 4