ImmutableArray Builder unexpected IndexOutOfRangeException

The following code throws an IndexOutOfRangeexception:

var builder = ImmutableArray.CreateBuilder<Color>(5);
builder[3] = Colors.Red;

I expected this would work, as the documentation says the following:

ImmutableArray<T>.CreateBuilder<T>(Int32) Creates a mutable array that can be converted to an ImmutableArray without allocating new memory; Int32 = The initial capacity of the builder. returns a Builder

Builder class: A writable array accessor that can be converted into an ImmutableArray instance without allocating extra memory.

Builder[int32] Gets or sets the item at the specified index.

Nothing in the docs says this would be an invalid expectation.

The same code for a basic array passes:

var colors = new Color[5];
colors[3] = Colors.Red;

I expected to get "a mutable array" by using a Builder but a regular mutable array behaves differently than the Builder.

For my app’s purpose, indices are keys, and I need to be able to set the item at a given index just like a basic array.

Edit:

This works:

var arr = new Color[5];
arr[3] = Colors.Red;
var array  = arr.ToImmutableArray();

This doesn’t:

var builder = ImmutableArray.CreateBuilder<Color>(5);
builder[3] = Colors.Red;
var array = builder.ToImmutable();

For my question, I can accomplish it via the above but take the penalty of additional allocation.

>Solution :

ImmutableArray<T>.Builder has the same semantics as List<T>. Therefore, creating one with a count actually gives you one with a specified capacity and a count of 0. And just like with a list, accessing elements above the count is an error.

Instead, set Count directly to forcibly resize the array, filling it with default values:

var builder = ImmutableArray.CreateBuilder<Color>();
builder.Count = 5; // this will increase capacity if needed
builder[3] = Colors.Red; // no more errors!

Leave a Reply