Browse Source

Grid visualizer:

- refactored value providers
- values are obtained from debugger only for displayed columns
- scrolls to top when new variable inspected

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4577 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Martin Koníček 16 years ago
parent
commit
4daa29a0eb
  1. 3
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
  2. 39
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs
  3. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/LazyListView.cs
  4. 79
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ObjectValue.cs
  5. 27
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs
  6. 50
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs
  7. 26
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs
  8. 3
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/VirtualizingIEnumerable.cs
  9. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/PresentationBindings/GridViewColumnHider.cs
  10. 41
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/PresentationBindings/ScrollUtils.cs
  11. 48
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/IEnumerableExtensions.cs
  12. 23
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/Lookup.cs

3
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj

@ -145,9 +145,12 @@ @@ -145,9 +145,12 @@
<Compile Include="Src\Visualizers\Graph\TreeModel\NonPublicMembersNode.cs" />
<Compile Include="Src\Visualizers\Graph\TreeModel\PropertyNode.cs" />
<Compile Include="Src\Visualizers\GridVisualizer\SelectedProperties.cs" />
<Compile Include="Src\Visualizers\GridVisualizer\ValueProviders\GridValuesProvider.cs" />
<Compile Include="Src\Visualizers\PresentationBindings\GridViewColumnHider.cs" />
<Compile Include="Src\Visualizers\PresentationBindings\ScrollUtils.cs" />
<Compile Include="Src\Visualizers\PresentationBindings\TooltipVisibilityConverter.cs" />
<Compile Include="Src\Visualizers\Utils\AtomicType.cs" />
<Compile Include="Src\Visualizers\Utils\IEnumerableExtensions.cs" />
<Compile Include="Src\Visualizers\Utils\ITreeNode.cs" />
<Compile Include="Src\Visualizers\Utils\LinqUtils.cs" />
<Compile Include="Src\Visualizers\Utils\ListHelper.cs" />

39
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs

@ -39,7 +39,11 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -39,7 +39,11 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
private void btnInspect_Click(object sender, RoutedEventArgs e)
{
// clear ListView
listView.ItemsSource = null;
ScrollViewer listViewScroller = listView.GetScrollViewer();
if (listViewScroller != null)
listViewScroller.ScrollToVerticalOffset(0);
this.debuggerService = DebuggerService.CurrentDebugger as WindowsDebugger;
if (debuggerService == null)
@ -56,35 +60,40 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -56,35 +60,40 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
}
if (val != null && !val.IsNull)
{
DebugType iListType, listItemType;
IList<MemberInfo> itemTypeMembers = null;
GridValuesProvider gridValuesProvider;
// Value is IList?
DebugType iListType, listItemType;
if (val.Type.ResolveIListImplementation(out iListType, out listItemType))
{
var valuesProvider = new ListValuesProvider(val.ExpressionTree, iListType, listItemType);
var virtCollection = new VirtualizingCollection<ObjectValue>(valuesProvider);
itemTypeMembers = valuesProvider.GetItemTypeMembers();
var listValuesProvider = new ListValuesProvider(val.ExpressionTree, iListType, listItemType);
var virtCollection = new VirtualizingCollection<ObjectValue>(listValuesProvider);
this.listView.ItemsSource = virtCollection;
gridValuesProvider = listValuesProvider;
}
else
{
// Value is IEnumerable?
DebugType iEnumerableType, itemType;
if (val.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType))
{
var lazyListViewWrapper = new LazyListView<ObjectValue>(this.listView);
var iEnumerableValuesProvider = new EnumerableValuesProvider(val.ExpressionTree, iEnumerableType, itemType);
itemTypeMembers = iEnumerableValuesProvider.GetItemTypeMembers();
lazyListViewWrapper.ItemsSource = new VirtualizingIEnumerable<ObjectValue>(iEnumerableValuesProvider.ItemsSource);
var enumerableValuesProvider = new EnumerableValuesProvider(val.ExpressionTree, iEnumerableType, itemType);
lazyListViewWrapper.ItemsSource = new VirtualizingIEnumerable<ObjectValue>(enumerableValuesProvider.ItemsSource);
gridValuesProvider = enumerableValuesProvider;
}
else
{
// Value cannot be displayed in GridVisualizer
return;
}
}
IList<MemberInfo> itemTypeMembers = gridValuesProvider.GetItemTypeMembers();
// create ListView columns
createGridViewColumns((GridView)this.listView.View, itemTypeMembers);
this.columnHider = new GridViewColumnHider((GridView)this.listView.View);
// fill column-choosing ComboBox
this.selectedProperties = initializeSelectedPropertiesWithEvents(itemTypeMembers);
cmbColumns.ItemsSource = this.selectedProperties;
}
@ -119,11 +128,11 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -119,11 +128,11 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
var columnName = propertySeleted.Name;
if (propertySeleted.IsSelected)
{
columnHider.ShowColumn(columnName);
this.columnHider.ShowColumn(columnName);
}
else
{
columnHider.HideColumn(columnName);
this.columnHider.HideColumn(columnName);
}
}
}

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/LazyListView.cs

@ -37,7 +37,7 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -37,7 +37,7 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
set
{
this.itemsSource = value;
this.itemsSource.RequestNextItems(14);
this.itemsSource.RequestNextItems(25);
this.listView.ItemsSource = value;
}
}

79
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ObjectValue.cs

@ -18,40 +18,77 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -18,40 +18,77 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
/// </summary>
public class ObjectValue
{
// couldn't be properties loaded lazily? - when listview databinding asks for key, we could ask fetch the value from debugger
// Used to be able to expand items of IEnumerable
// Now we rely on PermanentReference to be able to get member values on demand. With IList, PermanentReference can be replaced by Expression
public Value PermanentReference { get; private set; }
private Dictionary<string, ObjectProperty> properties = new Dictionary<string, ObjectProperty>();
/// <summary> Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members </summary>
private Dictionary<string, MemberInfo> memberFromNameMap;
internal ObjectValue(Dictionary<string, MemberInfo> memberFromNameMap)
{
this.memberFromNameMap = memberFromNameMap;
}
/// <summary>
/// Returns property with given name.
/// </summary>
public ObjectProperty this[string key]
{
get { return properties.GetValue(key); }
set { properties[key] = value; }
get
{
ObjectProperty property;
// has property with name 'propertyName' already been evaluated?
if(!this.properties.TryGetValue(key, out property))
{
if (this.PermanentReference == null) {
throw new DebuggerVisualizerException("Cannot get member of this ObjectValue - ObjectValue.PermanentReference is null");
}
MemberInfo memberInfo = this.memberFromNameMap.GetValue(key);
if (memberInfo == null) {
throw new DebuggerVisualizerException("Cannot get member value - no member found with name " + key);
}
property = createPropertyFromValue(key, this.PermanentReference.GetMemberValue(memberInfo));
this.properties.Add(key, property);
}
return property;
}
//set { properties[key] = value; }
}
public static ObjectValue Create(Debugger.Value value, DebugType type, BindingFlags bindingFlags)
public static ObjectValue Create(Debugger.Value value, Dictionary<string, MemberInfo> memberFromName)
{
ObjectValue result = new ObjectValue();
foreach(MemberInfo memberInfo in value.Type.GetMembers(bindingFlags))
ObjectValue result = new ObjectValue(memberFromName);
// remember PermanentReference for expanding IEnumerable
Value permanentReference = value.GetPermanentReference();
result.PermanentReference = permanentReference;
// cannot use GetMemberValues because memberValue does not have CodeTail anymore - we need the name of the member
/*foreach(MemberInfo memberInfo in permanentReference.Type.GetMembers(bindingFlags))
{
Value memberValue = value.GetMemberValue(memberInfo);
ObjectProperty property = new ObjectProperty();
property.Name = memberInfo.Name;
// property.Expression = ?.Age
// - cannot use expression,
// if the value is returned from an enumerator, it has no meaningful expression
property.IsAtomic = memberValue.Type.IsPrimitive;
property.IsNull = memberValue.IsNull;
//property.Value = memberValue.AsString;
property.Value = memberValue.IsNull ? "" : memberValue.InvokeToString();
result.properties.Add(property.Name, property);
}
Value memberValue = permanentReference.GetMemberValue(memberInfo);
result.properties.Add(createPropertyFromValue(memberInfo.Name, memberValue));
}*/
return result;
}
public static ObjectValue Create(Expression expr, DebugType type, BindingFlags bindingFlags)
private static ObjectProperty createPropertyFromValue(string propertyName, Value value)
{
ObjectProperty property = new ObjectProperty();
property.Name = propertyName;
// property.Expression = ?.Age
// - cannot use expression,
// if the value is returned from an enumerator, it has no meaningful expression
property.IsAtomic = value.Type.IsPrimitive;
property.IsNull = value.IsNull;
property.Value = value.IsNull ? "" : value.InvokeToString();
return property;
}
/*public static ObjectValue Create(Expression expr, DebugType type, BindingFlags bindingFlags)
{
ObjectValue result = new ObjectValue();
foreach(MemberInfo memberInfo in type.GetMembers(bindingFlags))
@ -69,6 +106,6 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -69,6 +106,6 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
result.properties.Add(property.Name, property);
}
return result;
}
}*/
}
}

27
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs

@ -17,23 +17,11 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -17,23 +17,11 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
/// <summary>
/// Provides <see cref="ObjectValue"/>s for debugee objects implementing IEnumerable.
/// </summary>
public class EnumerableValuesProvider
public class EnumerableValuesProvider : GridValuesProvider
{
private readonly Debugger.MetaData.BindingFlags bindingFlags =
BindingFlags.Public | BindingFlags.Instance | BindingFlags.Field | BindingFlags.GetProperty;
//private WindowsDebugger debugger;
private Expression targetObject;
private DebugType iEnumerableType;
private DebugType itemType;
public EnumerableValuesProvider(Expression targetObject, DebugType iEnumerableType, DebugType itemType)
:base(targetObject, iEnumerableType, itemType)
{
this.targetObject = targetObject;
this.iEnumerableType = iEnumerableType;
this.itemType = itemType;
this.itemsSource = enumerateItems();
}
@ -43,14 +31,9 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -43,14 +31,9 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
get { return this.itemsSource; }
}
public IList<MemberInfo> GetItemTypeMembers()
{
return itemType.GetMembers(this.bindingFlags);
}
private IEnumerable<ObjectValue> enumerateItems()
{
MethodInfo enumeratorMethod = iEnumerableType.GetMethod("GetEnumerator");
MethodInfo enumeratorMethod = collectionType.GetMethod("GetEnumerator");
Value enumerator = targetObject.Evaluate(WindowsDebugger.CurrentProcess).InvokeMethod(enumeratorMethod, null).GetPermanentReference();
MethodInfo moveNextMethod = enumerator.Type.GetMethod("MoveNext");
@ -58,8 +41,8 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -58,8 +41,8 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
while ((bool)enumerator.InvokeMethod(moveNextMethod, null).PrimitiveValue)
{
Value currentValue = enumerator.GetPropertyValue(currentproperty).GetPermanentReference();
yield return ObjectValue.Create(currentValue, this.itemType, this.bindingFlags);
Value currentValue = enumerator.GetPropertyValue(currentproperty);
yield return ObjectValue.Create(currentValue, this.memberFromNameMap);
}
}
}

50
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Martin Koníèek" email="martin.konicek@gmail.com"/>
// <version>$Revision$</version>
// </file>
using Debugger.MetaData;
using Debugger.AddIn.Visualizers.Utils;
using System;
using System.Collections;
using System.Collections.Generic;
using ICSharpCode.SharpDevelop.Services;
using ICSharpCode.NRefactory.Ast;
namespace Debugger.AddIn.Visualizers.GridVisualizer
{
/// <summary>
/// Provides <see cref="ObjectValue"/>s to be displayed in Grid visualizer.
/// Descandants implement getting values for IList and IEnumerable.
/// </summary>
public class GridValuesProvider
{
protected readonly Debugger.MetaData.BindingFlags memberBindingFlags =
BindingFlags.Public | BindingFlags.Instance | BindingFlags.Field | BindingFlags.GetProperty;
/// <summary> Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members </summary>
protected Dictionary<string, MemberInfo> memberFromNameMap;
protected Expression targetObject;
protected DebugType collectionType;
protected DebugType itemType;
public GridValuesProvider(Expression targetObject, DebugType collectionType, DebugType itemType)
{
this.targetObject = targetObject;
this.collectionType = collectionType;
this.itemType = itemType;
this.memberFromNameMap = this.GetItemTypeMembers().MakeDictionary(memberInfo => memberInfo.Name);
}
/// <summary>
/// Gets members that will be displayed as columns.
/// </summary>
public IList<MemberInfo> GetItemTypeMembers()
{
return itemType.GetMembers(this.memberBindingFlags);
}
}
}

26
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs

@ -18,23 +18,14 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -18,23 +18,14 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
/// <summary>
/// Provides <see cref="ObjectValue"/>s for debugee objects implementing IList.
/// </summary>
public class ListValuesProvider : IListValuesProvider<ObjectValue>
public class ListValuesProvider : GridValuesProvider, IListValuesProvider<ObjectValue>
{
private readonly Debugger.MetaData.BindingFlags bindingFlags =
BindingFlags.Public | BindingFlags.Instance | BindingFlags.Field | BindingFlags.GetProperty;
private Expression targetObject;
private DebugType iListType;
private DebugType listItemType;
private bool countEvaluated = false;
private int count = -1;
public ListValuesProvider(Expression targetObject, DebugType iListType, DebugType listItemType)
:base(targetObject, iListType, listItemType)
{
this.targetObject = targetObject;
this.iListType = iListType;
this.listItemType = listItemType;
}
public int GetCount()
@ -50,14 +41,9 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -50,14 +41,9 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
public ObjectValue GetItemAt(int index)
{
return ObjectValue.Create(
targetObject.AppendIndexer(index).Evaluate(WindowsDebugger.CurrentProcess).GetPermanentReference(),
//targetObject.AppendIndexer(index), // don't use PermanentReference - possible only for IList though
this.listItemType, this.bindingFlags);
}
public IList<MemberInfo> GetItemTypeMembers()
{
return listItemType.GetMembers(this.bindingFlags);
targetObject.AppendIndexer(index).Evaluate(WindowsDebugger.CurrentProcess),
//targetObject.AppendIndexer(index), // use Expression instead of value - possible only for IList though
this.memberFromNameMap);
}
// TODO move to Utils iListType.EvaluateCount(Expression targetObject)
@ -65,7 +51,7 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -65,7 +51,7 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
// or targetObject.EvaluateIListCount() <- calls ResolveIListImplementation
private int evaluateCount()
{
PropertyInfo countProperty = iListType.GetGenericInterface("System.Collections.Generic.ICollection").GetProperty("Count");
PropertyInfo countProperty = this.collectionType.GetGenericInterface("System.Collections.Generic.ICollection").GetProperty("Count");
try {
// Do not get string representation since it can be printed in hex later
Value countValue = targetObject.Evaluate(WindowsDebugger.CurrentProcess).GetPropertyValue(countProperty);

3
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/VirtualizingIEnumerable.cs

@ -13,7 +13,8 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -13,7 +13,8 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
/// <summary>
/// A wrapper around IEnumerable&lt;T&gt; with RequestNextItems method for pulling additional items
/// from the IEnumerable&lt;T&gt; when needed.
/// Can be used as source for LazyListView.
/// Can be used as source for <see cref="LazyListView" />.
/// (Used to wrap EnumerableValuesProvider.ItemsSource)
/// </summary>
public class VirtualizingIEnumerable<T> : ObservableCollection<T>
{

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/PresentationBindings/GridViewColumnHider.cs

@ -18,7 +18,7 @@ namespace Debugger.AddIn.Visualizers @@ -18,7 +18,7 @@ namespace Debugger.AddIn.Visualizers
}
/// <summary>
/// Utility for hiding and showing columns in GridView (GridViewColumn does not have Visility).
/// Utility for hiding and showing columns in GridView (GridViewColumn does not have Visility property).
/// </summary>
public class GridViewColumnHider
{

41
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/PresentationBindings/ScrollUtils.cs

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Martin Koníèek" email="martin.konicek@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Debugger.AddIn.Visualizers
{
/// <summary>
/// Description of ScrollUtils.
/// </summary>
public static class ScrollUtils
{
/// <summary>
/// Searches VisualTree of given object for a ScrollViewer.
/// </summary>
public static ScrollViewer GetScrollViewer(this DependencyObject o)
{
var scrollViewer = o as ScrollViewer;
if (scrollViewer != null) {
return scrollViewer;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++)
{
var child = VisualTreeHelper.GetChild(o, i);
var result = GetScrollViewer(child);
if (result != null) {
return result;
}
}
return null;
}
}
}

48
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/IEnumerableExtensions.cs

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Martin Koníèek" email="martin.konicek@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System.Collections.Generic;
using System.Linq;
using System;
namespace Debugger.AddIn.Visualizers.Utils
{
public static class IEnumerableExtensions
{
/// <summary>
/// Builds Dictionary for quickly searching a collection.
/// The keys must be unique.
/// </summary>
/// <param name="collection">Collection for which to build Dictionary.</param>
/// <param name="keySelector">Function returning key by which to index.</param>
public static Dictionary<K, V> MakeDictionary<K, V>(this IEnumerable<V> collection, Func<V, K> keySelector)
{
Dictionary<K, V> dictionary = new Dictionary<K, V>();
foreach (V item in collection)
{
K key = keySelector(item);
if (dictionary.ContainsKey(key)) throw new InvalidOperationException("MakeDictionary: key " + key + " seen twice");
dictionary[key] = item;
}
return dictionary;
}
/// <summary>
/// Builds Lookup for quickly searching a collection.
/// </summary>
/// <param name="collection">Collection for which to build Dictionary.</param>
/// <param name="keySelector">Function returning key by which to index.</param>
public static Lookup<K, V> MakeLookup<K, V>(this IEnumerable<V> collection, Func<V, K> keySelector)
{
Lookup<K, V> lookup = new Lookup<K, V>();
foreach (V item in collection)
{
lookup.Add(keySelector(item), item);
}
return lookup;
}
}
}

23
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/Lookup.cs

@ -14,19 +14,20 @@ namespace Debugger.AddIn.Visualizers.Utils @@ -14,19 +14,20 @@ namespace Debugger.AddIn.Visualizers.Utils
/// </summary>
public class Lookup<TKey, TValue>
{
private Dictionary<TKey, LookupValueCollection<TValue>> _dictionary;
/// <summary>Wrapped dictionary</summary>
private Dictionary<TKey, LookupValueCollection<TValue>> dictionary;
public Lookup()
{
_dictionary = new Dictionary<TKey, LookupValueCollection<TValue>>();
dictionary = new Dictionary<TKey, LookupValueCollection<TValue>>();
}
public LookupValueCollection<TValue> this[TKey key]
{
get
get
{
LookupValueCollection<TValue> values = null;
if (_dictionary.TryGetValue(key, out values))
if (dictionary.TryGetValue(key, out values))
{
return values;
}
@ -36,13 +37,13 @@ namespace Debugger.AddIn.Visualizers.Utils @@ -36,13 +37,13 @@ namespace Debugger.AddIn.Visualizers.Utils
public void Add(TKey key, TValue value)
{
LookupValueCollection<TValue> values = null;;
if (!_dictionary.TryGetValue(key, out values))
{
values = new LookupValueCollection<TValue>();
_dictionary.Add(key, values);
}
values.Add(value);
LookupValueCollection<TValue> values = null;
if (!dictionary.TryGetValue(key, out values))
{
values = new LookupValueCollection<TValue>();
dictionary.Add(key, values);
}
values.Add(value);
}
}
}

Loading…
Cancel
Save