提交 cb811332 编写于 作者: J Jon Hanna

Handle making argument to SameElements safe to enumerate twice within it.


Commit migrated from https://github.com/dotnet/corefx/commit/1a5a00d59488b26e67ae1b6fa06437fa5c482ada
上级 eea1852a
......@@ -227,10 +227,9 @@ internal static ParameterInfo[] GetParametersForValidation(MethodBase method, Ex
return pis;
}
internal static bool SameElements<T>(IEnumerable<T> replacement, IReadOnlyList<T> current) where T : class
internal static bool SameElements<T>(ICollection<T> replacement, IReadOnlyList<T> current) where T : class
{
Debug.Assert(current != null);
Debug.Assert(replacement == null | replacement is ICollection<T>);
if (replacement == current) // Relatively common case, so particularly useful to take the short-circuit.
{
return true;
......@@ -241,8 +240,38 @@ internal static ParameterInfo[] GetParametersForValidation(MethodBase method, Ex
return current.Count == 0;
}
return SameElementsInCollection(replacement, current);
}
internal static bool SameElements<T>(ref IEnumerable<T> replacement, IReadOnlyList<T> current) where T : class
{
Debug.Assert(current != null);
if (replacement == current) // Relatively common case, so particularly useful to take the short-circuit.
{
return true;
}
if (replacement == null) // Treat null as empty.
{
return current.Count == 0;
}
// Ensure arguments is safe to enumerate twice.
// If we have to build a collection, build a TrueReadOnlyCollection<T>
// so it won't be built a second time if used.
ICollection<T> replacementCol = replacement as ICollection<T>;
if (replacementCol == null)
{
replacement = replacementCol = replacement.ToReadOnly();
}
return SameElementsInCollection(replacementCol, current);
}
private static bool SameElementsInCollection<T>(ICollection<T> replacement, IReadOnlyList<T> current) where T : class
{
int count = current.Count;
if (((ICollection<T>)replacement).Count != count)
if (replacement.Count != count)
{
return false;
}
......
......@@ -88,10 +88,7 @@ public IndexExpression Update(Expression @object, IEnumerable<Expression> argume
{
if (@object == Object & arguments != null)
{
// Ensure arguments is safe to enumerate twice.
// (If this means a second call to ToReadOnly it will return quickly).
arguments = arguments as ICollection<Expression> ?? arguments.ToReadOnly();
if (ExpressionUtils.SameElements(arguments, Arguments))
if (ExpressionUtils.SameElements(ref arguments, Arguments))
{
return this;
}
......
......@@ -58,10 +58,7 @@ public InvocationExpression Update(Expression expression, IEnumerable<Expression
{
if (expression == Expression & arguments != null)
{
// Ensure arguments is safe to enumerate twice.
// (If this means a second call to ToReadOnly it will return quickly).
arguments = arguments as ICollection<Expression> ?? arguments.ToReadOnly();
if (ExpressionUtils.SameElements(arguments, Arguments))
if (ExpressionUtils.SameElements(ref arguments, Arguments))
{
return this;
}
......
......@@ -86,8 +86,7 @@ public ListInitExpression Update(NewExpression newExpression, IEnumerable<Elemen
{
if (newExpression == NewExpression & initializers != null)
{
initializers = initializers as ICollection<ElementInit> ?? initializers.ToReadOnly();
if (ExpressionUtils.SameElements(initializers, Initializers))
if (ExpressionUtils.SameElements(ref initializers, Initializers))
{
return this;
}
......
......@@ -124,8 +124,7 @@ public MemberInitExpression Update(NewExpression newExpression, IEnumerable<Memb
{
if (newExpression == NewExpression & bindings != null)
{
bindings = bindings as ICollection<MemberBinding> ?? bindings.ToReadOnly();
if (ExpressionUtils.SameElements(bindings, Bindings))
if (ExpressionUtils.SameElements(ref bindings, Bindings))
{
return this;
}
......
......@@ -39,8 +39,7 @@ public MemberListBinding Update(IEnumerable<ElementInit> initializers)
{
if (initializers != null)
{
initializers = initializers as ICollection<ElementInit> ?? initializers.ToReadOnly();
if (ExpressionUtils.SameElements(initializers, Initializers))
if (ExpressionUtils.SameElements(ref initializers, Initializers))
{
return this;
}
......
......@@ -42,8 +42,7 @@ public MemberMemberBinding Update(IEnumerable<MemberBinding> bindings)
{
if (bindings != null)
{
bindings = bindings as ICollection<MemberBinding> ?? bindings.ToReadOnly();
if (ExpressionUtils.SameElements(bindings, Bindings))
if (ExpressionUtils.SameElements(ref bindings, Bindings))
{
return this;
}
......
......@@ -66,10 +66,7 @@ public NewArrayExpression Update(IEnumerable<Expression> expressions)
// Explicit null check here as otherwise wrong parameter name will be used.
ContractUtils.RequiresNotNull(expressions, nameof(expressions));
// Ensure expressions is safe to enumerate twice.
// (If this means a second call to ToReadOnly it will return quickly).
expressions = expressions as ICollection<Expression> ?? expressions.ToReadOnly();
if (ExpressionUtils.SameElements(expressions, Expressions))
if (ExpressionUtils.SameElements(ref expressions, Expressions))
{
return this;
}
......
......@@ -82,10 +82,7 @@ protected internal override Expression Accept(ExpressionVisitor visitor)
/// <returns>This expression if no children changed, or an expression with the updated children.</returns>
public NewExpression Update(IEnumerable<Expression> arguments)
{
// Ensure arguments is safe to enumerate twice.
// (If this means a second call to ToReadOnly it will return quickly).
arguments = arguments as ICollection<Expression> ?? arguments.ToReadOnly();
if (ExpressionUtils.SameElements(arguments, Arguments))
if (ExpressionUtils.SameElements(ref arguments, Arguments))
{
return this;
}
......
......@@ -60,8 +60,7 @@ public RuntimeVariablesExpression Update(IEnumerable<ParameterExpression> variab
{
if (variables != null)
{
variables = variables as ICollection<ParameterExpression> ?? variables.ToReadOnly();
if (ExpressionUtils.SameElements(variables, Variables))
if (ExpressionUtils.SameElements(ref variables, Variables))
{
return this;
}
......
......@@ -52,8 +52,7 @@ public SwitchCase Update(IEnumerable<Expression> testValues, Expression body)
{
if (body == Body & testValues != null)
{
testValues = testValues as ICollection<Expression> ?? testValues.ToReadOnly();
if (ExpressionUtils.SameElements(testValues, TestValues))
if (ExpressionUtils.SameElements(ref testValues, TestValues))
{
return this;
}
......
......@@ -92,8 +92,7 @@ public SwitchExpression Update(Expression switchValue, IEnumerable<SwitchCase> c
{
if (switchValue == SwitchValue & defaultBody == DefaultBody & cases != null)
{
cases = cases as ICollection<SwitchCase> ?? cases.ToReadOnly();
if (ExpressionUtils.SameElements(cases, Cases))
if (ExpressionUtils.SameElements(ref cases, Cases))
{
return this;
}
......
......@@ -85,8 +85,7 @@ public TryExpression Update(Expression body, IEnumerable<CatchBlock> handlers, E
{
if (body == Body & @finally == Finally & fault == Fault)
{
handlers = handlers as ICollection<CatchBlock> ?? handlers.ToReadOnly();
if (ExpressionUtils.SameElements(handlers, Handlers))
if (ExpressionUtils.SameElements(ref handlers, Handlers))
{
return this;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册