Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[controls] Brush.Foo should return immutable instances (dotnet#3824)
When profiling a `dotnet new maui` app, with this package: https://github.com/jonathanpeppers/Mono.Profiler.Android The `alloc` report shows: Allocation summary Bytes Count Average Type name 39984 147 2 72 Microsoft.Maui.Controls.SolidColorBrush Stack trace: 38352 bytes from: (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr) Microsoft.Maui.Controls.VisualElement:.cctor () (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr) Microsoft.Maui.Controls.Brush:.cctor () Reviewing the `Brush` class, there are indeed 147 `SolidColorBrush` created on startup that are stored in fields. But what is weird about this, is that `SolidColorBrush` is mutable! public Color Color { get => (Color)GetValue(ColorProperty); set => SetValue(ColorProperty, value); } So I could literally write code like: Brush.Blue.Color = Colors.Red; Blue is red! (insert evil laughter?) I think the appropriate fix here is that all of these `static readonly` fields should just be properties that return a new `ImmutableBrush`. We can cache the values in fields on demand. Then someone can't do something evil like change `Blue` to `Red`? I reviewed WPF source code to check what they do, and they took a similar approach: https://github.com/dotnet/wpf/blob/5e8187344b2b561ef08b9ca2735cd89cbdd3c11e/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/brushes.cs#L33-L1586 We should make this API change now before MAUI is stable, and we have the side benefit to save 39984 bytes of memory on startup? I added tests for these scenarios, and discovered 3 typos for `Brush` colors that listed the wrong color.
- Loading branch information