6 votes

ImmutableArray<> se comporte différemment de Array<> pour les Select imbriqués avec indice

Je rencontre ce qui semble être un bug très bizarre dans ImmutableArray<> (avec BCL Immutable collections v1.0.12.0, runtime .NET 4.5) :

J'ai les deux structures identiques suivantes, exactement dans le même fichier source et dans le même espace de noms :

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;
    }
}

Ce qui suit entraînera une 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);

Si je projette les éléments1 dans ToArray() sur la première ligne au lieu de ToImmutableArray() tout fonctionne bien.

La seule différence entre les deux structs est que WeightedComponent est utilisé de manière extensive par le code précédent, alors que WeightedComponent2 n'est jamais utilisé auparavant (c'est pourquoi il peut ne pas être évident de reproduire le bogue).

Iterating on elements1 deux fois dans la même expression semblent être liés au problème, car si je le supprime, la Select fonctionne bien, mais il n'y a pas de tel problème avec elements2 . Il semble vraiment être lié à la façon dont le code derrière le ImmutableArray<> considère les deux structs (peut-être y a-t-il un mécanisme de cache ?)

Avez-vous une idée de ce qui pourrait causer ce problème ?

5voto

Andrew Arnott Points 35346

Ceci est dû à un bogue dans le ImmutableArray<T> énumérateur, déclenché la première fois que vous énumérez une instance vide de la collection. Le problème sera corrigé dans une prochaine version du paquet NuGet. En attendant, je vous suggère fortement d'éviter l'utilisation de ImmutableArray<T> .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X