Skip to content

Commit 5717fc2

Browse files
authored
Avoid Hashtable-related allocations in DataBindEngine (#6501)
The _valueConverterTable is a Hashtable that uses a struct-based key. It's boxing every time a lookup is performed or an add is performed.
1 parent 8853b34 commit 5717fc2

File tree

1 file changed

+21
-57
lines changed

1 file changed

+21
-57
lines changed

src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Data/DataBindEngine.cs

Lines changed: 21 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -368,13 +368,14 @@ internal IValueConverter GetDefaultValueConverter(Type sourceType,
368368
Type targetType,
369369
bool targetToSource)
370370
{
371-
IValueConverter result = _valueConverterTable[sourceType, targetType, targetToSource];
372-
373-
if (result == null)
371+
ValueConverterTableKey key = new ValueConverterTableKey(sourceType, targetType, targetToSource);
372+
if (!_valueConverterTable.TryGetValue(key, out IValueConverter result))
374373
{
375374
result = DefaultValueConverter.Create(sourceType, targetType, targetToSource, this);
376375
if (result != null)
377-
_valueConverterTable.Add(sourceType, targetType, targetToSource, result);
376+
{
377+
_valueConverterTable.Add(key, result);
378+
}
378379
}
379380

380381
return result;
@@ -657,63 +658,26 @@ private void OnLayoutUpdated(object sender, EventArgs e)
657658
//
658659
//------------------------------------------------------
659660

660-
// cache of default value converters (so that all uses of string-to-int can
661-
// share the same converter)
662-
class ValueConverterTable : Hashtable
661+
private readonly struct ValueConverterTableKey : IEquatable<ValueConverterTableKey>
663662
{
664-
struct Key
665-
{
666-
Type _sourceType, _targetType;
667-
bool _targetToSource;
668-
669-
public Key(Type sourceType, Type targetType, bool targetToSource)
670-
{
671-
_sourceType = sourceType;
672-
_targetType = targetType;
673-
_targetToSource = targetToSource;
674-
}
663+
private readonly Type _sourceType, _targetType;
664+
private readonly bool _targetToSource;
675665

676-
public override int GetHashCode()
677-
{
678-
return _sourceType.GetHashCode() + _targetType.GetHashCode();
679-
}
680-
681-
public override bool Equals(object o)
682-
{
683-
if (o is Key)
684-
{
685-
return (this == (Key)o);
686-
}
687-
return false;
688-
}
689-
690-
public static bool operator ==(Key k1, Key k2)
691-
{
692-
return k1._sourceType == k2._sourceType &&
693-
k1._targetType == k2._targetType &&
694-
k1._targetToSource == k2._targetToSource;
695-
}
696-
697-
public static bool operator !=(Key k1, Key k2)
698-
{
699-
return !(k1 == k2);
700-
}
701-
}
702-
703-
public IValueConverter this[Type sourceType, Type targetType, bool targetToSource]
666+
public ValueConverterTableKey(Type sourceType, Type targetType, bool targetToSource)
704667
{
705-
get
706-
{
707-
Key key = new Key(sourceType, targetType, targetToSource);
708-
object value = base[key];
709-
return (IValueConverter)value;
710-
}
668+
_sourceType = sourceType;
669+
_targetType = targetType;
670+
_targetToSource = targetToSource;
711671
}
712672

713-
public void Add(Type sourceType, Type targetType, bool targetToSource, IValueConverter value)
714-
{
715-
base.Add(new Key(sourceType, targetType, targetToSource), value);
716-
}
673+
public override int GetHashCode() => _sourceType.GetHashCode() + _targetType.GetHashCode();
674+
675+
public override bool Equals(object o) => o is ValueConverterTableKey other && Equals(other);
676+
677+
public bool Equals(ValueConverterTableKey other) =>
678+
_sourceType == other._sourceType &&
679+
_targetType == other._targetType &&
680+
_targetToSource == other._targetToSource;
717681
}
718682

719683
private sealed class DataBindEngineShutDownListener : ShutDownListener
@@ -741,7 +705,7 @@ internal override void OnShutDown(object target, object sender, EventArgs e)
741705
private UIElement _layoutElement;
742706
private ViewManager _viewManager = new ViewManager();
743707
private CommitManager _commitManager = new CommitManager();
744-
private ValueConverterTable _valueConverterTable = new ValueConverterTable();
708+
private Dictionary<ValueConverterTableKey, IValueConverter> _valueConverterTable = new Dictionary<ValueConverterTableKey, IValueConverter>();
745709
private PathParser _pathParser = new PathParser();
746710
private IAsyncDataDispatcher _defaultAsyncDataDispatcher;
747711
private HybridDictionary _asyncDispatchers;

0 commit comments

Comments
 (0)