Net4x.Collections.Immutable
1.0.0.26251
See the version list below for details.
dotnet add package Net4x.Collections.Immutable --version 1.0.0.26251
NuGet\Install-Package Net4x.Collections.Immutable -Version 1.0.0.26251
<PackageReference Include="Net4x.Collections.Immutable" Version="1.0.0.26251" />
<PackageVersion Include="Net4x.Collections.Immutable" Version="1.0.0.26251" />
<PackageReference Include="Net4x.Collections.Immutable" />
paket add Net4x.Collections.Immutable --version 1.0.0.26251
#r "nuget: Net4x.Collections.Immutable, 1.0.0.26251"
#:package Net4x.Collections.Immutable@1.0.0.26251
#addin nuget:?package=Net4x.Collections.Immutable&version=1.0.0.26251
#tool nuget:?package=Net4x.Collections.Immutable&version=1.0.0.26251
Net4x.Collections.Immutable
System.Collections.Immutable back-ported to .NET Framework 3.5, 4.0, 4.5 and 4.7.2.
The official System.Collections.Immutable package stopped supporting .NET Framework below 4.6.2 and never
supported 3.5 or 4.0 at all. This package provides the same types, in the same namespaces, with the same
signatures — so code written against the modern API compiles and runs unchanged on legacy targets.
dotnet add package Net4x.Collections.Immutable
Target frameworks
| Target | What you get |
|---|---|
net35 |
Full implementation |
net40 |
Full implementation |
net45 |
Full implementation |
net472 |
Full implementation, with Span<T>/Memory<T> coming from System.Memory |
netstandard2.0 |
A thin facade that simply depends on the official System.Collections.Immutable |
Because the netstandard2.0 asset forwards to the official package, a project that multi-targets legacy and
modern frameworks gets the real implementation where one exists and the back-port only where it doesn't.
On .NET Framework 4.6.2 and later the
Span<T>-based overloads resolve againstSystem.Memory; on 3.5/4.0/4.5 they resolve against the polyfill inNet4x.BaseExtensions. Reference thenet472asset (or newer) from any project targeting 4.6.2+ so the two do not mix.
What's included
Everything from the System.Collections.Immutable surface area:
| Namespace | Types |
|---|---|
System.Collections.Immutable |
ImmutableArray<T>, ImmutableList<T>, ImmutableDictionary<TKey,TValue>, ImmutableSortedDictionary<TKey,TValue>, ImmutableHashSet<T>, ImmutableSortedSet<T>, ImmutableStack<T>, ImmutableQueue<T> and their static factory classes and Builders |
System.Collections.Immutable |
ImmutableInterlocked — lock-free updates of immutable fields |
System.Linq |
ImmutableArrayExtensions — allocation-free LINQ over ImmutableArray<T> |
System.Runtime.InteropServices |
ImmutableCollectionsMarshal |
The IImmutableList<T>, IImmutableDictionary<TKey,TValue>, IImmutableSet<T>, IImmutableStack<T> and
IImmutableQueue<T> interfaces are included too, along with the classic IList/IDictionary/ISet
implementations, so the collections can be handed to APIs that predate them.
Usage
using System.Collections.Immutable;
// Arrays — a struct wrapping T[]; every operation returns a new instance.
var numbers = ImmutableArray.Create(1, 2, 3);
var more = numbers.Add(4); // numbers is still [1, 2, 3]
// Lists — an AVL tree, so Add/Insert/Remove are O(log n) and share structure.
var list = ImmutableList.Create("a", "b").Insert(1, "middle");
// Dictionaries and sets, with an optional comparer.
var map = ImmutableDictionary.Create<string, int>(StringComparer.OrdinalIgnoreCase)
.Add("One", 1);
bool found = map.ContainsKey("ONE"); // true — the comparer is honoured
var set = ImmutableSortedSet.Create(3, 1, 2); // enumerates 1, 2, 3
// Stacks and queues.
var stack = ImmutableStack<int>.Empty.Push(1).Push(2); // Peek() == 2
var queue = ImmutableQueue<int>.Empty.Enqueue(1).Enqueue(2); // Peek() == 1
Builders
Applying many changes one at a time allocates one collection per change. A Builder batches them and
produces a single immutable result:
var builder = ImmutableList.CreateBuilder<int>();
foreach (var item in source)
{
builder.Add(item);
}
ImmutableList<int> result = builder.ToImmutable();
Every collection offers CreateBuilder(...) on its static class and ToBuilder() on an existing instance.
Lock-free updates
ImmutableInterlocked swaps immutable values into a field with a compare-and-exchange loop, giving you a
concurrent collection without a lock:
private ImmutableDictionary<string, Session> _sessions = ImmutableDictionary<string, Session>.Empty;
public Session GetOrCreate(string id) =>
ImmutableInterlocked.GetOrAdd(ref _sessions, id, key => new Session(key));
LINQ without allocating
System.Linq.ImmutableArrayExtensions shadows the common Enumerable operators for ImmutableArray<T>,
avoiding the enumerator boxing you would otherwise pay for:
using System.Linq;
var evens = ImmutableArray.Create(1, 2, 3, 4).Where(x => x % 2 == 0);
var total = ImmutableArray.Create(1, 2, 3).Aggregate((a, b) => a + b);
Behavioural notes
These match the official implementation and surprise people often enough to be worth stating:
default(ImmutableArray<T>)is notImmutableArray<T>.Empty. It has no backing array;IsDefaultistrueand most members throw. UseImmutableArray<T>.Emptyfor an empty array.ImmutableArray<T>equality is reference equality of the backing array, not element-by-element. For a structural comparison useIStructuralEquatableorSequenceEqual.Aggregatewithout a seed returnsdefault(T)for an empty array rather than throwing, unlikeEnumerable.Aggregate.Add(key, value)on a dictionary is a no-op if the identical pair is already present and throwsArgumentExceptiononly when the key exists with a different value. UseSetItemto overwrite.- Operations that change nothing return the same instance —
Removeof an absent item,Addof an item a set already contains, and so on.
Building from source
The net35 target needs the desktop ResGen.exe, so a full build has to run under Visual Studio's MSBuild;
the dotnet CLI can build every other target (dotnet build -f net472).
License
Apache-2.0. See LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net35 is compatible. net40 is compatible. net403 was computed. net45 is compatible. net451 was computed. net452 was computed. net46 was computed. net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 3.5
- Net4x.BaseExtensions (>= 1.3.1.26243)
- Net4x.BaseTypes (>= 1.3.1.26243)
-
.NETFramework 4.0
- Net4x.BaseExtensions (>= 1.3.1.26243)
- Net4x.BaseTypes (>= 1.3.1.26243)
-
.NETFramework 4.5
- Net4x.BaseExtensions (>= 1.3.1.26243)
- Net4x.BaseTypes (>= 1.3.1.26243)
-
.NETFramework 4.7.2
- Net4x.BaseExtensions (>= 1.3.1.26243)
- Net4x.BaseTypes (>= 1.3.1.26243)
-
.NETStandard 2.0
- Net4x.BaseExtensions (>= 1.3.1.26243)
- Net4x.BaseTypes (>= 1.3.1.26243)
- System.Collections.Immutable (>= 1.5.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Net4x.Collections.Immutable:
| Package | Downloads |
|---|---|
|
Net4x.Extensions.Primitives
Primitives shared by framework extensions. |
|
|
Net4x.Reflection.Metadata
This packages provides a low-level .NET (ECMA-335) metadata reader and writer. It's geared for performance and is the ideal choice for building higher-level libraries that intend to provide their own object model, such as compilers. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.5.0.7 | 1,335 | 7/17/2026 |
| 2.5.0.6 | 213 | 2/2/2026 |
| 2.5.0.5 | 551 | 1/5/2026 |
| 2.5.0.4 | 274 | 12/30/2025 |
| 2.5.0.3 | 219 | 12/26/2025 |
| 2.5.0.2 | 197 | 12/21/2025 |
| 2.5.0.1 | 428 | 11/30/2025 |
| 2.5.0 | 1,923 | 4/4/2025 |
| 2.3.0 | 328 | 8/26/2023 |
| 2.3.0-at20230430063241 | 231 | 5/7/2023 |
| 2.2.1-at20230411061659 | 238 | 4/14/2023 |
| 2.1.0 | 368 | 4/8/2023 |
| 1.0.0.26251 | 45 | 9/10/2026 |
| 1.0.0 | 103 | 12/30/2025 |