VisualElement as IEnumerable

VisualElement with IEnumerable interface would provide the ability to use collection initializers. Enumerating a VisualElement would return all of its content container children.

The following code would then be possible:

var root = new VisualElement
{
    new Label { bindingPath = "counter"},
    new VisualElement
    {
        new Button { text = "Counter" },
        new Button { text= "Reset" }
    }
};

This combined with fluent interface extensions would provide nice-looking, expressive code.

var root = new Column
{
    new Label { bindingPath = "counter"},
    new Row
    {
        new Button()
            .Text("Counter")
            .Action(() => model.counter++),
        new Button()
            .Text("Reset")
            .Action(() => model.counter = 0),
    }
};

The new .NET MAUI does exactly this. Reference link.
If anyone wants to try this code, here’s upm package with samples.

3 Likes

Good suggestions, this has been forwarded to our PM for review.

This used to be the case back in the first implementations of VisualElement. I really like the collection initializers but it also comes with the other disavantages of IEnumerable: foreach used to do tons of gc allocations, methods that accept IEnumerable instead of VisualElements gets selected. For instance had a few cases in our unit tests where AreEqual(VisualElementA, VisualElementB) returned true because both were treated as empty collections.

We might bring in back in the future now that scripts run on an updated c# version but don’t hold your breath :slight_smile:

Thanks for replay, I would really like to know more about this :slight_smile:

Using foreach is optional and I can even see that the Enumerator of VisualContainer was a struct, so when those allocations were a problem?

NUnit has a special case for IEnumerable comparison. This can be corrected by implementing IEquatable interface. Were there other problems with that?

1 Like

That’s a good reason to follow up on CoreCLR:
https://xoofx.com/blog/2018/04/06/porting-unity-to-coreclr/
https://discussions.unity.com/t/762268

RyuJIT (Microsoft’s JIT compiler) can move those allocations to the stack (no GC at all), and the GC is much faster/better when it is needed. You also get main thread speeds close to what Burst delivers. If the only thing holding y’all back from CoreCLR is iOS (and maybe Switch? – It will run on Android and ps4/xbone) that’s sad.

1 Like