From 525a6d7f730bb7a1c5bfd4f82ad9d8e6383c80f0 Mon Sep 17 00:00:00 2001 From: Badre BSAILA <54767641+pedrobsaila@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:43:56 +0100 Subject: [PATCH] KeyedCollection debug view doesn't work (#96261) * KeyedCollection debug view doesn't work * fix remarks 1 * fix remarks 2 * add tests --- .../System/Collections/DebugView.Tests.cs | 40 ++++++++++++++++- .../ObjectModel/KeyedCollection.cs | 44 ++++++++++++++++++- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/libraries/Common/tests/System/Collections/DebugView.Tests.cs b/src/libraries/Common/tests/System/Collections/DebugView.Tests.cs index a67b7617ba681d..700f63213ebd88 100644 --- a/src/libraries/Common/tests/System/Collections/DebugView.Tests.cs +++ b/src/libraries/Common/tests/System/Collections/DebugView.Tests.cs @@ -47,6 +47,17 @@ private static IEnumerable TestDebuggerAttributes_GenericDictionaries( new ("[\"Two\"]", "2"), } }; + CustomKeyedCollection collection = new (); + collection.GetKeyForItemHandler = value => (2 * value).ToString(); + collection.InsertItem(0, 1); + collection.InsertItem(1, 3); + yield return new object[] { collection, + new KeyValuePair[] + { + new ("[\"2\"]", "1"), + new ("[\"6\"]", "3"), + } + }; } private static IEnumerable TestDebuggerAttributes_NonGenericDictionaries() @@ -173,7 +184,7 @@ public static IEnumerable TestDebuggerAttributes_Inputs() [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))] [MemberData(nameof(TestDebuggerAttributes_InputsPresentedAsDictionary))] - public static void TestDebuggerAttributes_Dictionary(IDictionary obj, KeyValuePair[] expected) + public static void TestDebuggerAttributes_Dictionary(object obj, KeyValuePair[] expected) { DebuggerAttributes.ValidateDebuggerDisplayReferences(obj); DebuggerAttributeInfo info = DebuggerAttributes.ValidateDebuggerTypeProxyProperties(obj); @@ -206,5 +217,32 @@ public static void TestDebuggerAttributes_Null(object obj) TargetInvocationException tie = Assert.Throws(() => Activator.CreateInstance(proxyType, (object)null)); Assert.IsType(tie.InnerException); } + + private class CustomKeyedCollection : KeyedCollection where TKey : notnull + { + public CustomKeyedCollection() : base() + { + } + + public CustomKeyedCollection(IEqualityComparer comparer) : base(comparer) + { + } + + public CustomKeyedCollection(IEqualityComparer comparer, int dictionaryCreationThreshold) : base(comparer, dictionaryCreationThreshold) + { + } + + public Func GetKeyForItemHandler { get; set; } + + protected override TKey GetKeyForItem(TValue item) + { + return GetKeyForItemHandler(item); + } + + public new void InsertItem(int index, TValue item) + { + base.InsertItem(index, item); + } + } } } diff --git a/src/libraries/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs b/src/libraries/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs index 7b5d39050eceef..d4fef7be1cb83f 100644 --- a/src/libraries/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs +++ b/src/libraries/System.ObjectModel/src/System/Collections/ObjectModel/KeyedCollection.cs @@ -8,7 +8,7 @@ namespace System.Collections.ObjectModel { [Serializable] - [DebuggerTypeProxy(typeof(CollectionDebugView<>))] + [DebuggerTypeProxy(typeof(KeyedCollection<,>.KeyedCollectionDebugView))] [DebuggerDisplay("Count = {Count}")] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public abstract class KeyedCollection : Collection where TKey : notnull @@ -280,5 +280,47 @@ private void RemoveKey(TKey key) keyCount--; } } + + private sealed class KeyedCollectionDebugView + { + private readonly KeyedCollection _collection; + + public KeyedCollectionDebugView(KeyedCollection collection) + { + ArgumentNullException.ThrowIfNull(collection); + _collection = collection; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public KeyedCollectionDebugViewItem[] Items + { + get + { + var items = new KeyedCollectionDebugViewItem[_collection.Count]; + for (int i = 0; i < items.Length; i++) + { + TItem item = _collection[i]; + items[i] = new KeyedCollectionDebugViewItem(_collection.GetKeyForItem(item), item); + } + return items; + } + } + + [DebuggerDisplay("{Value}", Name = "[{Key}]")] + internal readonly struct KeyedCollectionDebugViewItem + { + public KeyedCollectionDebugViewItem(TKey key, TItem value) + { + Key = key; + Value = value; + } + + [DebuggerBrowsable(DebuggerBrowsableState.Collapsed)] + public TKey Key { get; } + + [DebuggerBrowsable(DebuggerBrowsableState.Collapsed)] + public TItem Value { get; } + } + } } }