Основное отличие состоит в том, что объект Expando выполняет линейный поиск o (n) для каждого TryGetValue / TrySetValue.
В то время как в реальном словаре используется GetHashCode()
и выполняется поиск в очень маленьком сегменте элементов.
Это особенно заметно при создании больших объектов ExpandoObject, как в вашем тесте.
Это исходный код, который используют как TryGetValue, так и TrySetValue из ExpandoObject:
internal int GetValueIndexCaseSensitive(string name)
{
for (int i = 0; i < _keys.Length; i++)
{
if (string.Equals(_keys[i], name, StringComparison.Ordinal))
{
return i;
}
}
return -1;
}
Или посмотрите на код для BindGetOrInvokeMember
private DynamicMetaObject BindGetOrInvokeMember(DynamicMetaObjectBinder binder, string name, bool ignoreCase, DynamicMetaObject fallback, Func<DynamicMetaObject, DynamicMetaObject> fallbackInvoke)
{
ExpandoClass @class = Value.Class;
int valueIndex = @class.GetValueIndex(name, ignoreCase, Value);
ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "value");
Expression test = Expression.Call(typeof(RuntimeOps).GetMethod("ExpandoTryGetValue"), GetLimitedSelf(), Expression.Constant(@class, typeof(object)), Expression.Constant(valueIndex), Expression.Constant(name), Expression.Constant(ignoreCase), parameterExpression);
DynamicMetaObject dynamicMetaObject = new DynamicMetaObject(parameterExpression, BindingRestrictions.Empty);
if (fallbackInvoke != null)
{
dynamicMetaObject = fallbackInvoke(dynamicMetaObject);
}
dynamicMetaObject = new DynamicMetaObject(Expression.Block(new ParameterExpression[1]
{
parameterExpression
}, Expression.Condition(test, dynamicMetaObject.Expression, fallback.Expression, typeof(object))), dynamicMetaObject.Restrictions.Merge(fallback.Restrictions));
return AddDynamicTestAndDefer(binder, Value.Class, null, dynamicMetaObject);
}
Кроме того, имеется некоторое количество размышлений vodoo, блокировки и литья для ExpandoObject