/// <summary>
/// Visits an expression, casting the result back to the original expression type.
/// </summary>
/// <typeparam name="T">The type of the expression.</typeparam>
/// <param name="nodes">The expression to visit.</param>
/// <param name="callerName">The name of the calling method; used to report to report a better error message.</param>
/// <returns>The modified expression, if it or any subexpression was modified;
/// otherwise, returns the original expression.</returns>
/// <exception cref="InvalidOperationException">The visit method for this node returned a different type.</exception>
public ReadOnlyCollection <T> VisitAndConvert <T>(ReadOnlyCollection <T> nodes, string?callerName) where T : Expression
{
ContractUtils.RequiresNotNull(nodes, nameof(nodes));
T[]? newNodes = null;
for (int i = 0, n = nodes.Count; i < n; i++)
{
T?node = Visit(nodes[i]) as T;
if (node == null)
{
throw Error.MustRewriteToSameNode(callerName, typeof(T), callerName);
}
if (newNodes != null)
{
newNodes[i] = node;
}
else if (!object.ReferenceEquals(node, nodes[i]))
{
newNodes = new T[n];
for (int j = 0; j < i; j++)
{
newNodes[j] = nodes[j];
}
newNodes[i] = node;
}
}
if (newNodes == null)
{
return(nodes);
}
return(new TrueReadOnlyCollection <T>(newNodes));
}