-Avoid box allocations when enumerating IDictionary
This commit is contained in:
@@ -2041,9 +2041,19 @@ namespace Newtonsoft.Json.Serialization
|
||||
IDictionary targetDictionary = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(createdObjectDictionary) : (IDictionary)createdObjectDictionary;
|
||||
IDictionary newValues = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(value) : (IDictionary)value;
|
||||
|
||||
foreach (DictionaryEntry newValue in newValues)
|
||||
// Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations.
|
||||
IDictionaryEnumerator e = newValues.GetEnumerator();
|
||||
try
|
||||
{
|
||||
targetDictionary.Add(newValue.Key, newValue.Value);
|
||||
while (e.MoveNext())
|
||||
{
|
||||
DictionaryEntry entry = e.Entry;
|
||||
targetDictionary.Add(entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
(e as IDisposable)?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1050,49 +1050,60 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
int initialDepth = writer.Top;
|
||||
|
||||
foreach (DictionaryEntry entry in values)
|
||||
// Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations.
|
||||
IDictionaryEnumerator e = values.GetEnumerator();
|
||||
try
|
||||
{
|
||||
bool escape;
|
||||
string propertyName = GetPropertyName(writer, entry.Key, contract.KeyContract, out escape);
|
||||
|
||||
propertyName = (contract.DictionaryKeyResolver != null)
|
||||
? contract.DictionaryKeyResolver(propertyName)
|
||||
: propertyName;
|
||||
|
||||
try
|
||||
while (e.MoveNext())
|
||||
{
|
||||
object value = entry.Value;
|
||||
JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
|
||||
DictionaryEntry entry = e.Entry;
|
||||
|
||||
if (ShouldWriteReference(value, null, valueContract, contract, member))
|
||||
bool escape;
|
||||
string propertyName = GetPropertyName(writer, entry.Key, contract.KeyContract, out escape);
|
||||
|
||||
propertyName = (contract.DictionaryKeyResolver != null)
|
||||
? contract.DictionaryKeyResolver(propertyName)
|
||||
: propertyName;
|
||||
|
||||
try
|
||||
{
|
||||
writer.WritePropertyName(propertyName, escape);
|
||||
WriteReference(writer, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CheckForCircularReference(writer, value, null, valueContract, contract, member))
|
||||
object value = entry.Value;
|
||||
JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
|
||||
|
||||
if (ShouldWriteReference(value, null, valueContract, contract, member))
|
||||
{
|
||||
continue;
|
||||
writer.WritePropertyName(propertyName, escape);
|
||||
WriteReference(writer, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CheckForCircularReference(writer, value, null, valueContract, contract, member))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
writer.WritePropertyName(propertyName, escape);
|
||||
writer.WritePropertyName(propertyName, escape);
|
||||
|
||||
SerializeValue(writer, value, valueContract, null, contract, member);
|
||||
SerializeValue(writer, value, valueContract, null, contract, member);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (IsErrorHandled(underlyingDictionary, contract, propertyName, null, writer.ContainerPath, ex))
|
||||
catch (Exception ex)
|
||||
{
|
||||
HandleError(writer, initialDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
if (IsErrorHandled(underlyingDictionary, contract, propertyName, null, writer.ContainerPath, ex))
|
||||
{
|
||||
HandleError(writer, initialDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
(e as IDisposable)?.Dispose();
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
|
||||
|
||||
@@ -299,9 +299,19 @@ namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
foreach (DictionaryEntry item in _dictionary)
|
||||
// Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations.
|
||||
IDictionaryEnumerator e = _dictionary.GetEnumerator();
|
||||
try
|
||||
{
|
||||
array[arrayIndex++] = new KeyValuePair<TKey, TValue>((TKey)item.Key, (TValue)item.Value);
|
||||
while (e.MoveNext())
|
||||
{
|
||||
DictionaryEntry entry = e.Entry;
|
||||
array[arrayIndex++] = new KeyValuePair<TKey, TValue>((TKey)entry.Key, (TValue)entry.Value);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
(e as IDisposable)?.Dispose();
|
||||
}
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
|
||||
Reference in New Issue
Block a user