/// <summary>
/// Creates a <see cref="NewArrayExpression"/> that represents creating an array that has a specified rank.
/// </summary>
/// <param name="type">A <see cref="System.Type"/> that represents the element type of the array.</param>
/// <param name="bounds">An <see cref="IEnumerable{T}"/> that contains <see cref="Expression"/> objects to use to populate the <see cref="NewArrayExpression.Expressions"/> collection.</param>
/// <returns>A <see cref="NewArrayExpression"/> that has the <see cref="NodeType"/> property equal to <see cref="ExpressionType.NewArrayBounds"/> and the <see cref="NewArrayExpression.Expressions"/> property set to the specified value.</returns>
public static NewArrayExpression NewArrayBounds(Type type, IEnumerable <Expression> bounds)
{
ContractUtils.RequiresNotNull(type, nameof(type));
ContractUtils.RequiresNotNull(bounds, nameof(bounds));
if (type == typeof(void))
{
throw Error.ArgumentCannotBeOfTypeVoid(nameof(type));
}
TypeUtils.ValidateType(type, nameof(type));
if (type.IsByRef)
{
throw Error.TypeMustNotBeByRef(nameof(type));
}
if (type.IsPointer)
{
throw Error.TypeMustNotBePointer(nameof(type));
}
ReadOnlyCollection <Expression> boundsList = bounds.ToReadOnly();
int dimensions = boundsList.Count;
if (dimensions <= 0)
{
throw Error.BoundsCannotBeLessThanOne(nameof(bounds));
}
for (int i = 0; i < dimensions; i++)
{
Expression expr = boundsList[i];
RequiresCanRead(expr, nameof(bounds), i);
if (!TypeUtils.IsInteger(expr.Type))
{
throw Error.ArgumentMustBeInteger(nameof(bounds), i);
}
}
Type arrayType;
if (dimensions == 1)
{
//To get a vector, need call Type.MakeArrayType().
//Type.MakeArrayType(1) gives a non-vector array, which will cause type check error.
arrayType = type.MakeArrayType();
}
else
{
arrayType = type.MakeArrayType(dimensions);
}
return(NewArrayExpression.Make(ExpressionType.NewArrayBounds, arrayType, bounds.ToReadOnly()));
}