-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 targetDictionary = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(createdObjectDictionary) : (IDictionary)createdObjectDictionary;
|
||||||
IDictionary newValues = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(value) : (IDictionary)value;
|
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;
|
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;
|
while (e.MoveNext())
|
||||||
string propertyName = GetPropertyName(writer, entry.Key, contract.KeyContract, out escape);
|
|
||||||
|
|
||||||
propertyName = (contract.DictionaryKeyResolver != null)
|
|
||||||
? contract.DictionaryKeyResolver(propertyName)
|
|
||||||
: propertyName;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
object value = entry.Value;
|
DictionaryEntry entry = e.Entry;
|
||||||
JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
|
|
||||||
|
|
||||||
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);
|
object value = entry.Value;
|
||||||
WriteReference(writer, value);
|
JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
|
||||||
}
|
|
||||||
else
|
if (ShouldWriteReference(value, null, valueContract, contract, member))
|
||||||
{
|
|
||||||
if (!CheckForCircularReference(writer, 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)
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (IsErrorHandled(underlyingDictionary, contract, propertyName, null, writer.ContainerPath, ex))
|
|
||||||
{
|
{
|
||||||
HandleError(writer, initialDepth);
|
if (IsErrorHandled(underlyingDictionary, contract, propertyName, null, writer.ContainerPath, ex))
|
||||||
}
|
{
|
||||||
else
|
HandleError(writer, initialDepth);
|
||||||
{
|
}
|
||||||
throw;
|
else
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
(e as IDisposable)?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
writer.WriteEndObject();
|
writer.WriteEndObject();
|
||||||
|
|
||||||
|
|||||||
@@ -299,9 +299,19 @@ namespace Newtonsoft.Json.Utilities
|
|||||||
{
|
{
|
||||||
if (_dictionary != null)
|
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)
|
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||||
|
|||||||
Reference in New Issue
Block a user