Merge pull request #1151 from JonHanna/singleton_empty_array

Use singleton for zero-element arrays.
This commit is contained in:
James Newton-King
2017-01-09 15:11:14 +13:00
committed by GitHub
11 changed files with 69 additions and 39 deletions
+1 -1
View File
@@ -538,7 +538,7 @@ namespace Newtonsoft.Json
Guid g;
if (s.Length == 0)
{
data = new byte[0];
data = CollectionUtils.ArrayEmpty<byte>();
}
else if (ConvertUtils.TryConvertGuid(s, out g))
{
+1 -1
View File
@@ -146,7 +146,7 @@ namespace Newtonsoft.Json
byte[] data;
if (_stringReference.Length == 0)
{
data = new byte[0];
data = CollectionUtils.ArrayEmpty<byte>();
}
else if (_stringReference.Length == 36 && ConvertUtils.TryConvertGuid(_stringReference.ToString(), out g))
{
@@ -88,7 +88,7 @@ namespace Newtonsoft.Json.Linq.JsonPath
return JPath.Evaluate(pathFilters, root, t, false);
}
return new JToken[0];
return CollectionUtils.ArrayEmpty<JToken>();
}
public override bool IsMatch(JToken root, JToken t)
@@ -2274,7 +2274,7 @@ namespace Newtonsoft.Json.Serialization
return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.OverrideCreator, id);
}
newObject = objectContract.OverrideCreator(new object[0]);
newObject = objectContract.OverrideCreator(CollectionUtils.ArrayEmpty<object>());
}
else if (objectContract.DefaultCreator != null &&
(!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || objectContract.ParameterizedCreator == null))
@@ -745,7 +745,7 @@ namespace Newtonsoft.Json.Serialization
bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty);
SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, new int[0]);
SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, CollectionUtils.ArrayEmpty<int>());
if (hasWrittenMetadataObject)
{
@@ -29,12 +29,16 @@ using System.Collections.ObjectModel;
using System.Reflection;
using System.Text;
using System.Collections;
using System.Diagnostics;
#if NET20
using Newtonsoft.Json.Utilities.LinqBridge;
#else
using System.Linq;
#endif
using System.Globalization;
#if !(NET20 || NET35 || NET40 || PORTABLE40)
using System.Runtime.CompilerServices;
#endif
using Newtonsoft.Json.Serialization;
namespace Newtonsoft.Json.Utilities
@@ -340,9 +344,30 @@ namespace Newtonsoft.Json.Utilities
}
Array multidimensionalArray = Array.CreateInstance(type, dimensions.ToArray());
CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, new int[0]);
CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, ArrayEmpty<int>());
return multidimensionalArray;
}
// 4.6 has Array.Empty<T> to return a cached empty array. Lacking that in other
// frameworks, Enumerable.Empty<T> happens to be implemented as a cached empty
// array in all versions (in .NET Core the same instance as Array.Empty<T>).
// This includes the internal Linq bridge for 2.0.
// Since this method is simple and only 11 bytes long in a release build it's
// pretty much guaranteed to be inlined, giving us fast access of that cached
// array. With 4.5 and up we use AggressiveInlining just to be sure, so it's
// effectively the same as calling Array.Empty<T> even when not available.
#if !(NET20 || NET35 || NET40 || PORTABLE40)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static T[] ArrayEmpty<T>()
{
T[] array = Enumerable.Empty<T>() as T[];
Debug.Assert(array != null);
// Defensively guard against a version of Linq where Enumerable.Empty<T> doesn't
// return an array, but throw in debug versions so a better strategy can be
// used if that ever happens.
return array ?? new T[0];
}
}
}
@@ -37,7 +37,7 @@ namespace Newtonsoft.Json.Utilities
{
public virtual IEnumerable<string> GetDynamicMemberNames(T instance)
{
return new string[0];
return CollectionUtils.ArrayEmpty<string>();
}
public virtual bool TryBinaryOperation(T instance, BinaryOperationBinder binder, object arg, out object result)
@@ -166,7 +166,7 @@ namespace Newtonsoft.Json.Utilities
private delegate DynamicMetaObject Fallback(DynamicMetaObject errorSuggestion);
private static readonly Expression[] NoArgs = new Expression[0];
private static Expression[] NoArgs => CollectionUtils.ArrayEmpty<Expression>();
private static IEnumerable<Expression> GetArgs(params DynamicMetaObject[] args)
{
@@ -158,7 +158,7 @@ namespace Newtonsoft.Json.Utilities
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
{
DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { });
DynamicMetaObject retMetaObject = _innerBinder.Bind(target, CollectionUtils.ArrayEmpty<DynamicMetaObject>());
NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
@@ -87,40 +87,45 @@ namespace Newtonsoft.Json.Utilities
{
ParameterInfo[] parametersInfo = method.GetParameters();
Expression[] argsExpression = new Expression[parametersInfo.Length];
IList<ByRefParameter> refParameterMap = new List<ByRefParameter>();
for (int i = 0; i < parametersInfo.Length; i++)
Expression[] argsExpression;
IList<ByRefParameter> refParameterMap;
if (parametersInfo.Length == 0)
{
ParameterInfo parameter = parametersInfo[i];
Type parameterType = parameter.ParameterType;
bool isByRef = false;
if (parameterType.IsByRef)
argsExpression = CollectionUtils.ArrayEmpty<Expression>();
refParameterMap = CollectionUtils.ArrayEmpty<ByRefParameter>();
}
else
{
argsExpression = new Expression[parametersInfo.Length];
refParameterMap = new List<ByRefParameter>();
for (int i = 0; i < parametersInfo.Length; i++)
{
parameterType = parameterType.GetElementType();
isByRef = true;
}
Expression indexExpression = Expression.Constant(i);
Expression paramAccessorExpression = Expression.ArrayIndex(argsParameterExpression, indexExpression);
Expression argExpression = EnsureCastExpression(paramAccessorExpression, parameterType, !isByRef);
if (isByRef)
{
ParameterExpression variable = Expression.Variable(parameterType);
refParameterMap.Add(new ByRefParameter
ParameterInfo parameter = parametersInfo[i];
Type parameterType = parameter.ParameterType;
bool isByRef = false;
if (parameterType.IsByRef)
{
Value = argExpression,
Variable = variable,
IsOut = parameter.IsOut
});
parameterType = parameterType.GetElementType();
isByRef = true;
}
argExpression = variable;
Expression indexExpression = Expression.Constant(i);
Expression paramAccessorExpression = Expression.ArrayIndex(argsParameterExpression, indexExpression);
Expression argExpression = EnsureCastExpression(paramAccessorExpression, parameterType, !isByRef);
if (isByRef)
{
ParameterExpression variable = Expression.Variable(parameterType);
refParameterMap.Add(new ByRefParameter {Value = argExpression, Variable = variable, IsOut = parameter.IsOut});
argExpression = variable;
}
argsExpression[i] = argExpression;
}
argsExpression[i] = argExpression;
}
Expression callExpression;
@@ -90,7 +90,7 @@ namespace Newtonsoft.Json.Utilities
#if !(PORTABLE40 || PORTABLE)
EmptyTypes = Type.EmptyTypes;
#else
EmptyTypes = new Type[0];
EmptyTypes = CollectionUtils.ArrayEmpty<Type>();
#endif
}