I'm not an expert on native code, so I won't go into a lot of detail here, but I still think I can give you enough information to answer the question
NativeArray's can be used anywhere if you want to, but are primarily used within Unity's Job system. And their ecs system (or dots) uses it aswell (at the moment of writing, dots is still in preview, as in beta).
Unity's job system is made to be both fast and safe for multithreading. By that I mean that they do a lot of checks and add some limitations, to make sure you can't get some common errors when writing multithreaded code, as the architecture simply won't allow you to do so.
Those limitations inlude the fact that you are not allowed to reference classes inside jobs for instance (only structs). This is great as it means that you can't modify the same value in 2 jobs run at the same time, you can't accidentally do that as each job gets a copy of the value, meaning 2 jobs never get the same value in memory. On the other side, this also means that for the same reason, 2 jobs run after each other can't modify the same value.
Meet NativeContainers. They are structs that point to a piece of Native memory, meaning they can be used inside the job system and if 2 jobs are run after each other they can still access the same (native) memory. Unity then build their safety system around these NativeContainers. Meaning for instance that if you do try to write to the same memory in a NativeContainer from 2 different jobs (that can run at the same time), Unity will throw errors telling you that you are not allowed to do that and should make sure 1 of the jobs is dependent on the other to be completed first.
Another advantage is that because Unity forces you into a certain pattern with a lot of limitations, which includes using NativeCollections, Unity can optimize a lot of things for you when you enable the Burst compiler. Meaning you can write highly performant C# code. Which can be a huge difference (depending on the scenario).
There are however some rules applied to NativeArrays. These rules are basically there to ensure you use the NativeArray correctly.
- unlike regular arrays which allow you to populate it with instances of both classes and structs, the NativeArray only allows you to popuate it with structs.
- You have to dispose the NativeArray after you are done with it. Else you'll get memory leaks. This is because the NativeArray uses native memory instead of managed memory. For managed memory, the garbage collector makes sure data that is no longer referenced gets dealocated. This is not the case with the memory allocated for the NativeArray, you have to deallocate that memory yourself by calling Dispose.
You can find more background information about the safety system here.
As for when to use it:
I personally wouldn't advise you to use it if you are not also using the jobs system (Or dots as that uses the jobs system aswell), as the difference in performance might not even be noticable when used in regular Unity projects while the disadvantages remain. But don't take my word for it, check it yourself to be sure (in build, as Unity does a lot of extra checks in the editor that slow it down)
If you are using the jobs system, you should use them as you can't use regular arrays inside jobs.
There isn't really a point of showing you how to use a NaiveArray outside of the Job System (other then perhaps plugins already done in the other answer), and giving an example of the Job System requires me to explain a lot of the Job system itself which falls outside of the scope of this answer. So instead I would advise you see this example here, or to search for examples about unity's Job system.