diff --git a/Orm/Xtensive.Orm/Core/Extensions/EnumerableExtensions.cs b/Orm/Xtensive.Orm/Core/Extensions/EnumerableExtensions.cs index 3ff66c294..06fc18695 100644 --- a/Orm/Xtensive.Orm/Core/Extensions/EnumerableExtensions.cs +++ b/Orm/Xtensive.Orm/Core/Extensions/EnumerableExtensions.cs @@ -582,5 +582,11 @@ public static List SortTopologically(this IEnumerable va var result = TopologicalSorter.Sort(graph); return result.HasLoops ? null : result.SortedNodes.SelectToList(node => node.Value); } + + internal static IReadOnlyList ToReadOnlyList(this IEnumerable seq) => + seq switch { + IReadOnlyList roList => roList, + var s => s?.ToList() + }; } } diff --git a/Orm/Xtensive.Orm/Linq/ExpressionVisitor.cs b/Orm/Xtensive.Orm/Linq/ExpressionVisitor.cs index 4ee023d76..29c4b3190 100644 --- a/Orm/Xtensive.Orm/Linq/ExpressionVisitor.cs +++ b/Orm/Xtensive.Orm/Linq/ExpressionVisitor.cs @@ -21,7 +21,7 @@ public abstract class ExpressionVisitor(bool isCaching = false) : System.Linq.Ex { private readonly Dictionary cache = isCaching ? new() : null; - protected virtual IReadOnlyList VisitExpressionList(IReadOnlyList expressions) => + protected virtual IEnumerable VisitExpressionList(IReadOnlyList expressions) => VisitList(expressions, Visit); public override Expression Visit(Expression e) @@ -69,7 +69,7 @@ protected virtual ElementInit VisitElementInitializer(ElementInit initializer) /// /// The original element initializer list. /// Visit result. - protected virtual IReadOnlyList VisitElementInitializerList(ReadOnlyCollection original) => + protected virtual IEnumerable VisitElementInitializerList(ReadOnlyCollection original) => VisitList(original, VisitElementInitializer); /// @@ -236,29 +236,31 @@ protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBind /// /// The original binding list. /// Visit result. - protected virtual IReadOnlyList VisitBindingList(ReadOnlyCollection original) => + protected virtual IEnumerable VisitBindingList(ReadOnlyCollection original) => VisitList(original, VisitBinding); - public static IReadOnlyList VisitList(IReadOnlyList original, Func func) where T : class + public static IEnumerable VisitList(IReadOnlyList original, Func func) where T : class { - T[] ar = null; - for (int i = 0, n = original.Count; i < n; i++) { + for (int i = 0, n = original.Count; i < n; ++i) { var originalValue = original[i]; - var p = func(originalValue); - if (ar != null) { - ar[i] = p; - } - else if (!ReferenceEquals(p, originalValue)) { - ar = new T[n]; - for (int j = 0; j < i; j++) { - ar[j] = original[j]; - } - ar[i] = p; + if (func(originalValue) is var p && !ReferenceEquals(p, originalValue)) { + return VisitListIterator(original, func, p, i); } } - return ar?.AsSafeWrapper() ?? original; + return original; } + private static IEnumerable VisitListIterator(IReadOnlyList original, Func func, T p, int pIdx) where T : class + { + for (var i = 0; i < pIdx; ++i) { + yield return original[i]; + } + yield return p; + for (int i = pIdx + 1, n = original.Count; i < n; ++i) { + yield return func(original[i]); + } + } + protected override MemberListBinding VisitMemberListBinding(MemberListBinding binding) { var bindingInitializers = binding.Initializers; diff --git a/Orm/Xtensive.Orm/Orm/Linq/Expressions/Visitors/OwnerRemover.cs b/Orm/Xtensive.Orm/Orm/Linq/Expressions/Visitors/OwnerRemover.cs index 39d19f790..d5945cc54 100644 --- a/Orm/Xtensive.Orm/Orm/Linq/Expressions/Visitors/OwnerRemover.cs +++ b/Orm/Xtensive.Orm/Orm/Linq/Expressions/Visitors/OwnerRemover.cs @@ -67,7 +67,7 @@ internal override Expression VisitConstructorExpression(ConstructorExpression ex var nativeBingings = expression.NativeBindings .Zip(newNativeBindings) .ToDictionary(item => item.First.Key, item => item.Second); - return new ConstructorExpression(expression.Type, bindings, nativeBingings, expression.Constructor, newConstructorArguments); + return new ConstructorExpression(expression.Type, bindings, nativeBingings, expression.Constructor, newConstructorArguments.ToReadOnlyList()); } internal override Expression VisitEntityExpression(EntityExpression expression)