Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ImmutableArray<> behaves differently than Array<> for nested Select with index

I am encountering what seems to be a very weird bug in ImmutableArray<> (with BCL Immutable collections v1.0.12.0, runtime .NET 4.5):

I have the following two identical structs exactly in the same source file under the same namespace:

public struct WeightedComponent {
    public readonly IComponent Component;
    public readonly decimal Weight;

    public WeightedComponent(IComponent component, decimal weight) {
        this.Component = component;
        this.Weight = weight;
    }
}

public struct WeightedComponent2 {
    public readonly IComponent Component;
    public readonly decimal Weight;

    public WeightedComponent2(IComponent component, decimal weight) {
        this.Component = component;
        this.Weight = weight;
    }
}

The following will throw an exception:

var elements1 = new[] { 1, 2, 3 }.Select(wc => new WeightedComponent(null, 0)).ToImmutableArray();
var foo = elements1.Select((e1, i1) => elements1.Select((e2, i2) => 0).ToArray()).ToArray();
if (foo.Length != 3) throw new Exception("Error: " + foo.Length); //Error: 1

var elements2 = new[] { 1, 2, 3 }.Select(wc => new WeightedComponent2(null, 0)).ToImmutableArray();
var foo2 = elements2.Select((e1, i1) => elements2.Select((e2, i2) => 0).ToArray()).ToArray();
if (foo2.Length != 3) throw new Exception("Error: " + foo.Length);

If I project elements1 into ToArray() on the first line instead of ToImmutableArray(), everything works fine.

The only difference between the two structs is that WeightedComponent is used extensively by the code before, while WeightedComponent2 is never used before (this is why it may not be obvious to reproduce the bug).

Iterating on elements1 twice in the same expression seem to be related to the issue, as if I remove it the Select works fine, but there is no such problem with elements2. It really seems to be related to the way the code behind ImmutableArray<> is considering both structs (maybe there is a caching mechanism?)

Do you have any idea what could be causing this?

like image 912
Erwin Mayer Avatar asked Sep 10 '13 11:09

Erwin Mayer


1 Answers

This is due to a bug in the ImmutableArray<T> enumerator, triggered the first time you enumerate an empty instance of the collection. A future version of the NuGet package will have the issue fixed. In the meantime, I strongly suggest you avoid use of ImmutableArray<T>.

like image 193
Andrew Arnott Avatar answered Sep 25 '22 07:09

Andrew Arnott