# Do First and foremost: **DO try to avoid having to use this library in the first place.** Chances are you're here because you're stuck on netfx for reason X and need method Y to hit razor-thin performance goals. `ArrayPool` solves almost every "I need a temporary array" problem without any of this danger, and `Array.AsSpan()` works as normal even for array fakes. If you can, try to use everything else and `Span` over it BEFORE resorting to using this library. - **DO back it with stack or native memory only** (`stackalloc`; `NativeMemory.Alloc` / `Marshal.AllocHGlobal`). The facade is sound *only* because a non-heap address fails the GC's heap range check, so the collector skips any reference to it and never inspects your header. - **DO size the region with `ComputeMinimumSafeSizeFor`.** It returns the worst-case requirement (header + maximum alignment padding + elements), so its result is valid for any pointer you end up passing. `Use` then validates your requested length against the size you declared and throws before touching memory if it doesn't fit. - **DO tell the truth about `sizeofRaw`.** All validation is done against the size you declare at construction; it is the one thing the library must take your word for. Declare more bytes than you actually own and the library will happily stamp into and hand out memory that isn't yours. - **DO consume the array entirely within the synchronous scope that owns the backing memory** (read / copy / synchronous-blocking API) and retain nothing. - **DO restrict to APIs that finish using the buffer before they return** (e.g. blocking `FileStream.Read` in sync mode). Only a blocking call keeps your frame alive for the whole operation and retains nothing after, so use-after-free is structurally impossible. - **DO treat memory provenance as an invariant enforced at the allocation site**. Only *you*, the caller, know where the `void*` came from that `ArrayFacadeHandle` received. The library cannot protect you from giving it heap memory. # Do not - **DO NOT back it with GC-heap memory** (writing the fake header into a real/rented `byte[]`, a pinned object, etc.). On the heap the collector believes the bytes are its own, and since you never went through the allocator, its bookkeeping and your forgery disagree → corruption on the next collection. **There is no safe heap variant.** - **DO NOT let the reference escape its owning scope.** No storing in a field/longer-lived local, no closure capture, no returning, no boxing, no handing it to anything deferred (`async`/`Task`-returning APIs, thread-pool work, a retaining `IDisposable`, a later callback). Heap-backing corrupts *immediately*; an escaped stack/native reference corrupts *eventually* (dangling pointer to a popped frame or freed block). A `T[]` parameter/delegate contract cannot enforce this. - **DO NOT pass a fake to deferred/capturing/cross-thread APIs.** `BeginRead`/`*Async`/socket async, anything stashing the array in a field or queueing it. The buffer outlives your frame and any references to the memory dangle. - **DO NOT lock on a fake or take its identity hash.** `lock (fake)`/`Monitor.Enter`, `RuntimeHelpers.GetHashCode(fake)`, or keying a reference-based collection (`Dictionary`, `ConditionalWeakTable`) with it can force the runtime to inflate the header word into a sync block table entry, enrolling an "object" the GC doesn't own into a runtime-managed registry. Undefined behavior at best. - **DO NOT pin through `GCHandle.Alloc`.** Behavior on a non-heap target is undefined (retail may no-op; checked/debug runtimes assert heap membership) and it buys nothing over `fixed` (or just using the pointer you already had, OR `.AsSpan()` on runtimes that have it or using `System.Memory`). - **DO NOT attempt to circumvent `Array.MaxLength`.** The field inside `Array` that holds the length is always `int`. Passed in `length`s are checked against that value. - **DO NOT EVER trust external data** to be safe or even valid. Giving unchecked pointers and sizes from memory regions you haven't allocated yourself to `ArrayFacadeHandle.ctor` is likely to cause AVs.