mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-10 18:11:04 +09:00
Unify debug views of immutable dictionaries (#100745)
* Unify debug views of immutable dictionaries Fixes #94289 - Updates the way the debugger displays the remaining dictionaries (Frozen, Immutable, ImmutableSorted, Concurrent) to present their keys and values in separate columns. - Fixes debugger views of Builder classes of immutable collections. Previous custom implementations incorrectly treated the Builder classes as immutable. * Fixed tests of debugger attributes with immutable and concurrent generic dictionaries * Removed tests superseded by DebugView.Tests. * Fixed DebugView.Tests of cuncurrent and immutable generic dictionaries which failed on .Net Framework * Fix ns2.0 build. --------- Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>
This commit is contained in:
parent
41d854fd44
commit
8bcbe18072
14 changed files with 99 additions and 195 deletions
|
@ -1,7 +1,10 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
@ -47,8 +50,8 @@ namespace System.Collections.Tests
|
|||
new ("[\"Two\"]", "2"),
|
||||
}
|
||||
};
|
||||
CustomKeyedCollection<string, int> collection = new ();
|
||||
collection.GetKeyForItemHandler = value => (2 * value).ToString();
|
||||
CustomKeyedCollection<string, int> collection = new();
|
||||
collection.GetKeyForItemHandler = value => (2 * value).ToString();
|
||||
collection.InsertItem(0, 1);
|
||||
collection.InsertItem(1, 3);
|
||||
yield return new object[] { collection,
|
||||
|
@ -58,6 +61,53 @@ namespace System.Collections.Tests
|
|||
new ("[\"6\"]", "3"),
|
||||
}
|
||||
};
|
||||
|
||||
yield return new object[] { new ConcurrentDictionary<int, string>(new KeyValuePair<int, string>[] { new(1, "One"), new(2, "Two") }),
|
||||
new KeyValuePair<string, string>[]
|
||||
{
|
||||
new ("[1]", "\"One\""),
|
||||
new ("[2]", "\"Two\""),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> TestDebuggerAttributes_AdditionalGenericDictionaries()
|
||||
{
|
||||
yield return new object[] { new Dictionary<int, string> { { 1, "One" }, { 2, "Two" } }.ToFrozenDictionary(),
|
||||
new KeyValuePair<string, string>[]
|
||||
{
|
||||
new ("[1]", "\"One\""),
|
||||
new ("[2]", "\"Two\""),
|
||||
}
|
||||
};
|
||||
yield return new object[] { new Dictionary<int, string> { { 1, "One" }, { 2, "Two" } }.ToImmutableDictionary(),
|
||||
new KeyValuePair<string, string>[]
|
||||
{
|
||||
new ("[1]", "\"One\""),
|
||||
new ("[2]", "\"Two\""),
|
||||
}
|
||||
};
|
||||
yield return new object[] { new Dictionary<int, string> { { 1, "One" }, { 2, "Two" } }.ToImmutableDictionary().ToBuilder(),
|
||||
new KeyValuePair<string, string>[]
|
||||
{
|
||||
new ("[1]", "\"One\""),
|
||||
new ("[2]", "\"Two\""),
|
||||
}
|
||||
};
|
||||
yield return new object[] { new Dictionary<int, string> { { 1, "One" }, { 2, "Two" } }.ToImmutableSortedDictionary(),
|
||||
new KeyValuePair<string, string>[]
|
||||
{
|
||||
new ("[1]", "\"One\""),
|
||||
new ("[2]", "\"Two\""),
|
||||
}
|
||||
};
|
||||
yield return new object[] { new Dictionary<int, string> { { 1, "One" }, { 2, "Two" } }.ToImmutableSortedDictionary().ToBuilder(),
|
||||
new KeyValuePair<string, string>[]
|
||||
{
|
||||
new ("[1]", "\"One\""),
|
||||
new ("[2]", "\"Two\""),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> TestDebuggerAttributes_NonGenericDictionaries()
|
||||
|
@ -162,12 +212,14 @@ namespace System.Collections.Tests
|
|||
|
||||
public static IEnumerable<object[]> TestDebuggerAttributes_InputsPresentedAsDictionary()
|
||||
{
|
||||
var testCases = TestDebuggerAttributes_NonGenericDictionaries()
|
||||
.Concat(TestDebuggerAttributes_AdditionalGenericDictionaries());
|
||||
#if !NETFRAMEWORK
|
||||
return TestDebuggerAttributes_NonGenericDictionaries()
|
||||
return testCases
|
||||
.Concat(TestDebuggerAttributes_GenericDictionaries());
|
||||
#else
|
||||
// In .Net Framework only non-generic dictionaries are displayed in a dictionary format by the debugger.
|
||||
return TestDebuggerAttributes_NonGenericDictionaries();
|
||||
// In .Net Framework, the generic dictionaries that are part of the framework are displayed in a list format by the debugger.
|
||||
return testCases;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
Link="System\Collections\HashHelpers.cs" />
|
||||
<Compile Include="$(CoreLibSharedDir)System\Collections\Concurrent\IProducerConsumerCollectionDebugView.cs"
|
||||
Link="System\Collections\Concurrent\IProducerConsumerCollectionDebugView.cs" />
|
||||
<Compile Include="$(CoreLibSharedDir)System\Collections\Generic\DebugViewDictionaryItem.cs"
|
||||
Link="Common\System\Collections\Generic\DebugViewDictionaryItem.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -2733,12 +2733,17 @@ namespace System.Collections.Concurrent
|
|||
}
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||
public KeyValuePair<TKey, TValue>[] Items
|
||||
public DebugViewDictionaryItem<TKey, TValue>[] Items
|
||||
{
|
||||
get
|
||||
{
|
||||
var items = new KeyValuePair<TKey, TValue>[_dictionary.Count];
|
||||
_dictionary.CopyTo(items, 0);
|
||||
var keyValuePairs = new KeyValuePair<TKey, TValue>[_dictionary.Count];
|
||||
_dictionary.CopyTo(keyValuePairs, 0);
|
||||
var items = new DebugViewDictionaryItem<TKey, TValue>[keyValuePairs.Length];
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
{
|
||||
items[i] = new DebugViewDictionaryItem<TKey, TValue>(keyValuePairs[i]);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -629,27 +629,6 @@ namespace System.Collections.Concurrent.Tests
|
|||
Assert.Equal(2, dictionary.Count);
|
||||
}
|
||||
|
||||
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
|
||||
public static void TestDebuggerAttributes()
|
||||
{
|
||||
DebuggerAttributes.ValidateDebuggerDisplayReferences(new ConcurrentDictionary<string, int>());
|
||||
ConcurrentDictionary<string, int> dict = new ConcurrentDictionary<string, int>();
|
||||
dict.TryAdd("One", 1);
|
||||
dict.TryAdd("Two", 2);
|
||||
DebuggerAttributeInfo info = DebuggerAttributes.ValidateDebuggerTypeProxyProperties(dict);
|
||||
PropertyInfo itemProperty = info.Properties.Single(pr => pr.GetCustomAttribute<DebuggerBrowsableAttribute>().State == DebuggerBrowsableState.RootHidden);
|
||||
KeyValuePair<string, int>[] items = itemProperty.GetValue(info.Instance) as KeyValuePair<string, int>[];
|
||||
Assert.Equal(dict, items);
|
||||
}
|
||||
|
||||
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
|
||||
public static void TestDebuggerAttributes_Null()
|
||||
{
|
||||
Type proxyType = DebuggerAttributes.GetProxyType(new ConcurrentDictionary<string, int>());
|
||||
TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => Activator.CreateInstance(proxyType, (object)null));
|
||||
Assert.IsType<ArgumentNullException>(tie.InnerException);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void TestNullComparer()
|
||||
{
|
||||
|
|
|
@ -12,11 +12,11 @@ The System.Collections.Immutable library is built-in as part of the shared frame
|
|||
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\InternalsVisibleTo.cs" />
|
||||
|
||||
<Compile Include="System\Polyfills.cs" />
|
||||
<Compile Include="System\Collections\ThrowHelper.cs" />
|
||||
<Compile Include="$(CoreLibSharedDir)System\Collections\HashHelpers.cs" Link="System\Collections\HashHelpers.cs" />
|
||||
|
||||
<Compile Include="$(CoreLibSharedDir)System\Collections\Generic\DebugViewDictionaryItem.cs" Link="Common\System\Collections\Generic\DebugViewDictionaryItem.cs" />
|
||||
<Compile Include="$(CoreLibSharedDir)System\Collections\Generic\IDictionaryDebugView.cs" Link="Common\System\Collections\Generic\IDictionaryDebugView.cs" />
|
||||
<Compile Include="System\Collections\Frozen\Constants.cs" />
|
||||
<Compile Include="System\Collections\Frozen\DefaultFrozenDictionary.cs" />
|
||||
<Compile Include="System\Collections\Frozen\DefaultFrozenSet.cs" />
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace System.Collections.Immutable
|
|||
/// </para>
|
||||
/// </remarks>
|
||||
[DebuggerDisplay("Count = {Count}")]
|
||||
[DebuggerTypeProxy(typeof(ImmutableDictionaryBuilderDebuggerProxy<,>))]
|
||||
[DebuggerTypeProxy(typeof(IDictionaryDebugView<,>))]
|
||||
public sealed class Builder : IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>, IDictionary
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -709,36 +709,4 @@ namespace System.Collections.Immutable
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A simple view of the immutable collection that the debugger can show to the developer.
|
||||
/// </summary>
|
||||
internal sealed class ImmutableDictionaryBuilderDebuggerProxy<TKey, TValue> where TKey : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// The collection to be enumerated.
|
||||
/// </summary>
|
||||
private readonly ImmutableDictionary<TKey, TValue>.Builder _map;
|
||||
|
||||
/// <summary>
|
||||
/// The simple view of the collection.
|
||||
/// </summary>
|
||||
private KeyValuePair<TKey, TValue>[]? _contents;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ImmutableDictionaryBuilderDebuggerProxy{TKey, TValue}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="map">The collection to display in the debugger</param>
|
||||
public ImmutableDictionaryBuilderDebuggerProxy(ImmutableDictionary<TKey, TValue>.Builder map)
|
||||
{
|
||||
Requires.NotNull(map, nameof(map));
|
||||
_map = map;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a simple debugger-viewable collection.
|
||||
/// </summary>
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||
public KeyValuePair<TKey, TValue>[] Contents => _contents ??= _map.ToArray(_map.Count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,16 +12,38 @@ namespace System.Collections.Immutable
|
|||
/// </summary>
|
||||
/// <typeparam name="TKey">The type of the dictionary's keys.</typeparam>
|
||||
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
|
||||
internal sealed class ImmutableDictionaryDebuggerProxy<TKey, TValue> : ImmutableEnumerableDebuggerProxy<KeyValuePair<TKey, TValue>> where TKey : notnull
|
||||
/// <remarks>
|
||||
/// This class should only be used with immutable dictionaries, since it
|
||||
/// caches the dictionary into an array for display in the debugger.
|
||||
/// </remarks>
|
||||
internal sealed class ImmutableDictionaryDebuggerProxy<TKey, TValue> where TKey : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// The dictionary to show to the debugger.
|
||||
/// </summary>
|
||||
private readonly IReadOnlyDictionary<TKey, TValue> _dictionary;
|
||||
|
||||
/// <summary>
|
||||
/// The contents of the dictionary, cached into an array.
|
||||
/// </summary>
|
||||
private DebugViewDictionaryItem<TKey, TValue>[]? _cachedContents;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ImmutableDictionaryDebuggerProxy{TKey, TValue}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="dictionary">The enumerable to show in the debugger.</param>
|
||||
/// <param name="dictionary">The dictionary to show in the debugger.</param>
|
||||
public ImmutableDictionaryDebuggerProxy(IReadOnlyDictionary<TKey, TValue> dictionary)
|
||||
: base(enumerable: dictionary)
|
||||
{
|
||||
Requires.NotNull(dictionary, nameof(dictionary));
|
||||
_dictionary = dictionary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the contents of the dictionary for display in the debugger.
|
||||
/// </summary>
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||
public DebugViewDictionaryItem<TKey, TValue>[] Contents => _cachedContents
|
||||
??= _dictionary.Select(kv => new DebugViewDictionaryItem<TKey, TValue>(kv)).ToArray(_dictionary.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace System.Collections.Immutable
|
|||
/// </para>
|
||||
/// </remarks>
|
||||
[DebuggerDisplay("Count = {Count}")]
|
||||
[DebuggerTypeProxy(typeof(ImmutableSortedDictionaryBuilderDebuggerProxy<,>))]
|
||||
[DebuggerTypeProxy(typeof(IDictionaryDebugView<,>))]
|
||||
public sealed class Builder : IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>, IDictionary
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -645,35 +645,4 @@ namespace System.Collections.Immutable
|
|||
#endregion
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// A simple view of the immutable collection that the debugger can show to the developer.
|
||||
/// </summary>
|
||||
internal sealed class ImmutableSortedDictionaryBuilderDebuggerProxy<TKey, TValue> where TKey : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// The collection to be enumerated.
|
||||
/// </summary>
|
||||
private readonly ImmutableSortedDictionary<TKey, TValue>.Builder _map;
|
||||
|
||||
/// <summary>
|
||||
/// The simple view of the collection.
|
||||
/// </summary>
|
||||
private KeyValuePair<TKey, TValue>[]? _contents;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ImmutableSortedDictionaryBuilderDebuggerProxy{TKey, TValue}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="map">The collection to display in the debugger</param>
|
||||
public ImmutableSortedDictionaryBuilderDebuggerProxy(ImmutableSortedDictionary<TKey, TValue>.Builder map)
|
||||
{
|
||||
Requires.NotNull(map, nameof(map));
|
||||
_map = map;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a simple debugger-viewable collection.
|
||||
/// </summary>
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||
public KeyValuePair<TKey, TValue>[] Contents => _contents ??= _map.ToArray(_map.Count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -255,27 +255,6 @@ namespace System.Collections.Immutable.Tests
|
|||
Assert.Equal(5, populated.GetValueOrDefault("a", 1));
|
||||
}
|
||||
|
||||
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
|
||||
public void DebuggerAttributesValid()
|
||||
{
|
||||
DebuggerAttributes.ValidateDebuggerDisplayReferences(ImmutableDictionary.CreateBuilder<string, int>());
|
||||
ImmutableDictionary<int, string>.Builder builder = ImmutableDictionary.CreateBuilder<int, string>();
|
||||
builder.Add(1, "One");
|
||||
builder.Add(2, "Two");
|
||||
DebuggerAttributeInfo info = DebuggerAttributes.ValidateDebuggerTypeProxyProperties(builder);
|
||||
PropertyInfo itemProperty = info.Properties.Single(pr => pr.GetCustomAttribute<DebuggerBrowsableAttribute>().State == DebuggerBrowsableState.RootHidden);
|
||||
KeyValuePair<int, string>[] items = itemProperty.GetValue(info.Instance) as KeyValuePair<int, string>[];
|
||||
Assert.Equal(builder, items);
|
||||
}
|
||||
|
||||
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
|
||||
public static void TestDebuggerAttributes_Null()
|
||||
{
|
||||
Type proxyType = DebuggerAttributes.GetProxyType(ImmutableHashSet.Create<string>());
|
||||
TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => Activator.CreateInstance(proxyType, (object)null));
|
||||
Assert.IsType<ArgumentNullException>(tie.InnerException);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToImmutableDictionary()
|
||||
{
|
||||
|
|
|
@ -349,28 +349,6 @@ namespace System.Collections.Immutable.Tests
|
|||
enumerator.Dispose();
|
||||
}
|
||||
|
||||
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
|
||||
public void DebuggerAttributesValid()
|
||||
{
|
||||
DebuggerAttributes.ValidateDebuggerDisplayReferences(ImmutableDictionary.Create<int, int>());
|
||||
ImmutableDictionary<string, int> dict = ImmutableDictionary.Create<string, int>().Add("One", 1).Add("Two", 2);
|
||||
DebuggerAttributeInfo info = DebuggerAttributes.ValidateDebuggerTypeProxyProperties(dict);
|
||||
|
||||
object rootNode = DebuggerAttributes.GetFieldValue(ImmutableDictionary.Create<string, string>(), "_root");
|
||||
DebuggerAttributes.ValidateDebuggerDisplayReferences(rootNode);
|
||||
PropertyInfo itemProperty = info.Properties.Single(pr => pr.GetCustomAttribute<DebuggerBrowsableAttribute>().State == DebuggerBrowsableState.RootHidden);
|
||||
KeyValuePair<string, int>[] items = itemProperty.GetValue(info.Instance) as KeyValuePair<string, int>[];
|
||||
Assert.Equal(dict, items);
|
||||
}
|
||||
|
||||
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
|
||||
public static void TestDebuggerAttributes_Null()
|
||||
{
|
||||
Type proxyType = DebuggerAttributes.GetProxyType(ImmutableHashSet.Create<string>());
|
||||
TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => Activator.CreateInstance(proxyType, (object)null));
|
||||
Assert.IsType<ArgumentNullException>(tie.InnerException);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clear_NoComparer_ReturnsEmptyWithoutComparer()
|
||||
{
|
||||
|
|
|
@ -255,27 +255,6 @@ namespace System.Collections.Immutable.Tests
|
|||
Assert.Equal(5, populated.GetValueOrDefault("a", 1));
|
||||
}
|
||||
|
||||
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
|
||||
public void DebuggerAttributesValid()
|
||||
{
|
||||
DebuggerAttributes.ValidateDebuggerDisplayReferences(ImmutableSortedDictionary.CreateBuilder<string, int>());
|
||||
ImmutableSortedDictionary<int, string>.Builder builder = ImmutableSortedDictionary.CreateBuilder<int, string>();
|
||||
builder.Add(1, "One");
|
||||
builder.Add(2, "Two");
|
||||
DebuggerAttributeInfo info = DebuggerAttributes.ValidateDebuggerTypeProxyProperties(builder);
|
||||
PropertyInfo itemProperty = info.Properties.Single(pr => pr.GetCustomAttribute<DebuggerBrowsableAttribute>().State == DebuggerBrowsableState.RootHidden);
|
||||
KeyValuePair<int, string>[] items = itemProperty.GetValue(info.Instance) as KeyValuePair<int, string>[];
|
||||
Assert.Equal(builder, items);
|
||||
}
|
||||
|
||||
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
|
||||
public static void TestDebuggerAttributes_Null()
|
||||
{
|
||||
Type proxyType = DebuggerAttributes.GetProxyType(ImmutableSortedDictionary.CreateBuilder<int, string>());
|
||||
TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => Activator.CreateInstance(proxyType, (object)null));
|
||||
Assert.IsType<ArgumentNullException>(tie.InnerException);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValueRef()
|
||||
{
|
||||
|
|
|
@ -402,28 +402,6 @@ namespace System.Collections.Immutable.Tests
|
|||
Assert.Equal(0, dictionary.Remove(2).Count);
|
||||
}
|
||||
|
||||
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
|
||||
public void DebuggerAttributesValid()
|
||||
{
|
||||
DebuggerAttributes.ValidateDebuggerDisplayReferences(ImmutableSortedDictionary.Create<string, int>());
|
||||
ImmutableSortedDictionary<int, int> dict = ImmutableSortedDictionary.Create<int, int>().Add(1, 2).Add(2, 3).Add(3, 4);
|
||||
DebuggerAttributeInfo info = DebuggerAttributes.ValidateDebuggerTypeProxyProperties(dict);
|
||||
|
||||
object rootNode = DebuggerAttributes.GetFieldValue(ImmutableSortedDictionary.Create<string, string>(), "_root");
|
||||
DebuggerAttributes.ValidateDebuggerDisplayReferences(rootNode);
|
||||
PropertyInfo itemProperty = info.Properties.Single(pr => pr.GetCustomAttribute<DebuggerBrowsableAttribute>().State == DebuggerBrowsableState.RootHidden);
|
||||
KeyValuePair<int, int>[] items = itemProperty.GetValue(info.Instance) as KeyValuePair<int, int>[];
|
||||
Assert.Equal(dict, items);
|
||||
}
|
||||
|
||||
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
|
||||
public static void TestDebuggerAttributes_Null()
|
||||
{
|
||||
Type proxyType = DebuggerAttributes.GetProxyType(ImmutableSortedDictionary.Create<int, int>());
|
||||
TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => Activator.CreateInstance(proxyType, (object)null));
|
||||
Assert.IsType<ArgumentNullException>(tie.InnerException);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValueRef()
|
||||
{
|
||||
|
|
|
@ -11,9 +11,7 @@ namespace System.Collections.Generic
|
|||
|
||||
public IDictionaryDebugView(IDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(dictionary);
|
||||
|
||||
_dict = dictionary;
|
||||
_dict = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
|
||||
}
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||
|
@ -39,9 +37,7 @@ namespace System.Collections.Generic
|
|||
|
||||
public DictionaryKeyCollectionDebugView(ICollection<TKey> collection)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(collection);
|
||||
|
||||
_collection = collection;
|
||||
_collection = collection ?? throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||
|
@ -62,9 +58,7 @@ namespace System.Collections.Generic
|
|||
|
||||
public DictionaryValueCollectionDebugView(ICollection<TValue> collection)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(collection);
|
||||
|
||||
_collection = collection;
|
||||
_collection = collection ?? throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue