# Introduction to unmanaged collections

> Introduction to unmanaged collections.

The `Unity.Collections` namespace provides unmanaged C# containers that you can use in jobs and Burst-compiled code. The collections in this namespace fall into the following categories:

* Collection types with safety checks to ensure they're used in a thread-safe way and properly disposed of. These types are in the `Unity.Collections` namespace and their names start with `Native`.
* Collection types without safety checks. These types are in the `Unity.Collections.LowLevel.Unsafe` namespace and their names start with `Unsafe`.

The remaining collection types that don't fit into these categories aren't allocated and don't contain any pointers. These types only contain small amounts of data, and their disposal and thread safety aren't a concern.

## Safety handles and checks

`Native` collection types carry Unity's [`AtomicSafetyHandle`](/engine/7000.0/script-reference/unity/collections/lowlevel/unsafe/atomicsafetyhandle.md), which performs validation for access, disposal, and job dependencies. The `Unsafe` equivalents don't carry these safety handles. These safety handles are separate from index bounds checking, and several `Unsafe` types, such as [`UnsafeList`](/engine/7000.0/script-reference/unity/collections/lowlevel/unsafe/unsafelist1.md) and [`UnsafePtrList`](/engine/7000.0/script-reference/unity/collections/lowlevel/unsafe/unsafeptrlist1.md), bounds-check their indexers via `CollectionHelper.CheckIndexInRange`. This works in the same way as the equivalent conditional checks in `Native` types.

Checks are always enabled in the Editor, and in [Player builds](/engine/7000.0/manual/building-and-publishing/building-introduction.md) with the Checked [managed code variant](/engine/7000.0/manual/building-and-publishing/managed-code-variants.md#managed-code-variant). The only way to make these checks fully zero-cost is to run in a Player build that doesn't include safety checks.

It's important to understand that disabling safety checks in the Editor doesn't compile out these checks:

* The [**Burst** menu](/engine/7000.0/manual/programming-environment/script-compilation/burst/editor-reference-overview/editor-burst-menu.md) option to disable safety checks has a specific and limited effect: when a subset of checks are called from Burst-compiled code, they're compiled out. If Burst is disabled, or if a method runs outside of Burst for any other reason, this option has no effect on that code.
* Disabling the **jobs debugger** disables a subset of jobs debugger threading checks, but doesn't reduce the overall cost of checks to zero.

Neither of these options reduces the cost of checks overall to zero.

### Native versus Unsafe collections

It's best practice to use `Native` collections over the `Unsafe` equivalents, because the safety handles catch access, disposal, and job-dependency errors. However, it's sometimes necessary to use the `Unsafe` equivalents, because `Native` collection types can't contain other `Native` collections. This limitation comes from how Unity implements the `Native` safety handles. For example, if you want a list of lists, you can use either `NativeList<UnsafeList<T>>` or `UnsafeList<UnsafeList<T>>`, but you can't use `NativeList<NativeList<T>>`.

Most `Native` collections are implemented as wrappers of their `Unsafe` counterparts. For example, `NativeList` is made up of an `UnsafeList` plus the handles that the safety checks use. Because of this wrapping, a `Native` type is not free even when checks are compiled out: the internal `Unsafe` collection introduces an extra pointer indirection, which adds cost by itself even in unchecked Player builds.

Several `Native` types have `Unsafe` equivalents, for example, [`NativeList`](/engine/7000.0/script-reference/unity/collections/nativelist1.md) has [`UnsafeList`](/engine/7000.0/script-reference/unity/collections/lowlevel/unsafe/unsafelist1.md), and [`NativeHashMap`](/engine/7000.0/script-reference/unity/collections/nativehashmap2.md) has [`UnsafeHashMap`](/engine/7000.0/script-reference/unity/collections/lowlevel/unsafe/unsafehashmap2.md).

The following table summarizes the comparative safety features of `Native` and `Unsafe` collection types:

| Behavior            | Native                                | Unsafe                                     |
| ------------------- | ------------------------------------- | ------------------------------------------ |
| Job safety checks   | Yes                                   | No                                         |
| Index bound checks  | Yes                                   | Partially (when safety checks are enabled) |
| Containing behavior | Can only contain `Unsafe` collections | Can contain either                         |

#### Passing collections by value

The way changes are reflected when you pass a collection by value differs between collection types:

* If you pass a `NativeList` by value and either write into the data or resize the list, the changes are reflected in the caller's copy of the list.
* If you pass an `UnsafeList` by value and write into the data, those writes are reflected in the caller's version. However, if you resize the list, that change is not reflected in the caller's copy, and moreover all subsequent writes are not reflected either.
* If you pass a `FixedList` by value, nothing is reflected in the caller's copy, because the entire contents are copied when you pass it.

## Additional resources

* [Collection types overview](/engine/7000.0/manual/analysis/performance-memory/collections/collection-types.md)
* [Parallel readers and writers](/engine/7000.0/manual/analysis/performance-memory/collections/parallel-readers.md)
