From 528de5869e305ec377d75098496ecaeadb949b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 27 Feb 2021 14:47:09 +0100 Subject: [PATCH] Fix multiple enumerations when ordering setting sources This was not spotted previously, because the base `Attribute` overrides `Equals()` to have semantics similar to structs (per-field equality) by using reflection. That masked the issue when strings were used, and migrating to `LocalisableString` revealed it, as that struct's implementation of equality currently uses instance checks. Whether `LocalisableString.Equals()` is the correct implementation may still be up for discussion, but allowing multiple enumeration is wrong anyway, since the underlying enumerables are live (one especially is a yield iterator, causing new object instances to be allocated). --- osu.Game/Configuration/SettingSourceAttribute.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Configuration/SettingSourceAttribute.cs b/osu.Game/Configuration/SettingSourceAttribute.cs index 65a5a6d1b4..d0d2480e62 100644 --- a/osu.Game/Configuration/SettingSourceAttribute.cs +++ b/osu.Game/Configuration/SettingSourceAttribute.cs @@ -139,9 +139,12 @@ namespace osu.Game.Configuration public static IEnumerable<(SettingSourceAttribute, PropertyInfo)> GetOrderedSettingsSourceProperties(this object obj) { - var original = obj.GetSettingsSourceProperties(); + var original = obj.GetSettingsSourceProperties().ToArray(); - var orderedRelative = original.Where(attr => attr.Item1.OrderPosition != null).OrderBy(attr => attr.Item1.OrderPosition); + var orderedRelative = original + .Where(attr => attr.Item1.OrderPosition != null) + .OrderBy(attr => attr.Item1.OrderPosition) + .ToArray(); var unordered = original.Except(orderedRelative); return orderedRelative.Concat(unordered);