From 7b03606402b8779872763595f8e11d3f12c0d98a Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 4 Oct 2025 18:44:10 +0200 Subject: [PATCH] Fix #3575: Uses of compiler-generated events getting swapped with non-generated events of same type --- .../TestCases/Pretty/PropertiesAndEvents.cs | 17 ++++++++++++++ .../PropertyAndEventBackingFieldLookup.cs | 23 ++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs index 367c53855..0206dade0 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PropertiesAndEvents.cs @@ -192,6 +192,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } + public event EventHandler Issue3575_AutoEvent; + public event EventHandler Issue3575_NonAuto; + + public event EventHandler Issue3575_Auto { + add { + } + remove { + } + } + + public event EventHandler Issue3575_NonAutoEvent { + add { + } + remove { + } + } + public int Getter(StringBuilder b) { return b.Length; diff --git a/ICSharpCode.Decompiler/Metadata/PropertyAndEventBackingFieldLookup.cs b/ICSharpCode.Decompiler/Metadata/PropertyAndEventBackingFieldLookup.cs index 9c05bd549..1688cd488 100644 --- a/ICSharpCode.Decompiler/Metadata/PropertyAndEventBackingFieldLookup.cs +++ b/ICSharpCode.Decompiler/Metadata/PropertyAndEventBackingFieldLookup.cs @@ -37,6 +37,8 @@ namespace ICSharpCode.Decompiler.Metadata var nameToFieldMap = new MultiDictionary(); + HashSet eventNames = new(); + foreach (var tdh in metadata.TypeDefinitions) { var type = metadata.GetTypeDefinition(tdh); @@ -72,6 +74,16 @@ namespace ICSharpCode.Decompiler.Metadata } } + // first get all names of events defined, so that we can make sure we don't accidentally + // associate the wrong backing field with the event, in case there is an event called "Something" + // without a backing field (i.e., custom event) as well as an auto/field event called "SomethingEvent" + // declared in the same type. + foreach (var edh in type.GetEvents()) + { + var ev = metadata.GetEventDefinition(edh); + eventNames.Add(metadata.GetString(ev.Name)); + } + foreach (var edh in type.GetEvents()) { var ev = metadata.GetEventDefinition(edh); @@ -83,15 +95,20 @@ namespace ICSharpCode.Decompiler.Metadata eventLookup[fieldHandle] = edh; } } - else if (nameToFieldMap.TryGetValues($"{name}Event", out fieldHandles)) + else { - foreach (var fieldHandle in fieldHandles) + var nameWithSuffix = $"{name}Event"; + if (!eventNames.Contains(nameWithSuffix) && nameToFieldMap.TryGetValues(nameWithSuffix, out fieldHandles)) { - eventLookup[fieldHandle] = edh; + foreach (var fieldHandle in fieldHandles) + { + eventLookup[fieldHandle] = edh; + } } } } + eventNames.Clear(); nameToFieldMap.Clear(); } }