Home > Mobile >  ImmutableArray Builder unexpected IndexOutOfRangeException
ImmutableArray Builder unexpected IndexOutOfRangeException

Time:01-15

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.

CodePudding user response:

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!

CodePudding user response:

You're trying to access a value that does not exist, (since you have not allocated any Color inside the array) giving you the IndexOutOfRangeException

To fix this error, you can either create a new array like this:

 var colors = new Color[]
 {
     Colors.Red,
     Colors.Green,
     Colors.Blue,
     // Etc.
 };

Or you can simply add the color you want.

colors.Add(Colors.Red);

Of course that this works with any other variable type, not only "Color"

CodePudding user response:

The ImmutableArray.CreateBuilder method creates a builder that can be used to create an immutable array of the specified size. However, when you try to access an index of the builder using the square bracket notation, you are getting an "Index out of bounds" exception because the builder is empty and does not have any elements at that index yet.

you can use the builder.Insert() method to insert an element at a specific index, like this:

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

Alternatively, you can first add elements to the builder before accessing them. For example, you can do something like this

var builder = ImmutableArray.CreateBuilder<Color>(5);
for(int i=0;i<5;i  )
{
    builder.Add(Colors.Black);
}
builder[3] = Colors.Red;

CodePudding user response:

ImmutableArray.CreateBuilder creates the array, but doesn't set the size. Therefore, if you call Count on builder, you'll get 0.

You can add elements to the collection...

builder.Add(Colors.Red);

...which will increase the size, or (as Etienne de Martel pointed out in a comment), you can do...

builder.Count = 5;

...which will set the size, allowing you to set individual elements directly.

  • Related