Skip to content

Commit 759d5a0

Browse files
authored
Optimize ExpressionComparer (#422)
1 parent caf75ba commit 759d5a0

File tree

1 file changed

+44
-46
lines changed

1 file changed

+44
-46
lines changed

Orm/Xtensive.Orm/Linq/Internals/ExpressionComparer.cs

Lines changed: 44 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Created: 2009.05.06
66

77
using System.Linq.Expressions;
8-
using Xtensive.Core;
8+
using System.Collections.ObjectModel;
99

1010
namespace Xtensive.Linq
1111
{
@@ -103,14 +103,38 @@ private bool Visit(Expression x, Expression y)
103103
}
104104
}
105105

106-
private bool VisitListInit(ListInitExpression x, ListInitExpression y)
106+
private bool ElementInitsAreEqual(ReadOnlyCollection<ElementInit> x, ReadOnlyCollection<ElementInit> y)
107107
{
108-
var self = this; // To allow struct's methods inside closures
109-
return VisitNew(x.NewExpression, y.NewExpression)
110-
&& x.Initializers.Count==y.Initializers.Count
111-
&& x.Initializers
112-
.Zip(y.Initializers)
113-
.All(p => self.VisitElementInit(p.First, p.Second));
108+
var count = x.Count;
109+
if (count != y.Count) {
110+
return false;
111+
}
112+
113+
for (int i = 0; i < count; ++i) {
114+
if (!VisitElementInit(x[i], y[i])) {
115+
return false;
116+
}
117+
}
118+
return true;
119+
}
120+
121+
private bool VisitListInit(ListInitExpression x, ListInitExpression y) =>
122+
VisitNew(x.NewExpression, y.NewExpression) && ElementInitsAreEqual(x.Initializers, y.Initializers);
123+
124+
private bool MemberBindingsAreEqual(ReadOnlyCollection<MemberBinding> xBindings, ReadOnlyCollection<MemberBinding> yBindings)
125+
{
126+
var count = xBindings.Count;
127+
if (count != yBindings.Count) {
128+
return false;
129+
}
130+
131+
for (int i = 0; i < count; ++i) {
132+
if (!VisitMemberBinding(xBindings[i], yBindings[i])) {
133+
return false;
134+
}
135+
}
136+
137+
return true;
114138
}
115139

116140
/// <summary>
@@ -119,45 +143,19 @@ private bool VisitListInit(ListInitExpression x, ListInitExpression y)
119143
/// <param name="x">The x.</param>
120144
/// <param name="y">The y.</param>
121145
/// <returns></returns>
122-
private bool VisitMemberInit(MemberInitExpression x, MemberInitExpression y)
123-
{
124-
var self = this; // To allow struct's methods inside closures
125-
return VisitNew(x.NewExpression, y.NewExpression)
126-
&& x.Bindings.Count==y.Bindings.Count
127-
&& x.Bindings
128-
.Zip(y.Bindings)
129-
.All(p => self.VisitMemberBinding(p.First, p.Second));
130-
}
146+
private bool VisitMemberInit(MemberInitExpression x, MemberInitExpression y) =>
147+
VisitNew(x.NewExpression, y.NewExpression) && MemberBindingsAreEqual(x.Bindings, y.Bindings);
131148

132-
private bool VisitMemberBinding(MemberBinding x, MemberBinding y)
133-
{
134-
var bindingType = x.BindingType;
135-
if (bindingType != y.BindingType || x.Member != y.Member)
136-
return false;
137-
var self = this; // To allow struct's methods inside closures
138-
switch (bindingType) {
139-
case MemberBindingType.Assignment:
140-
var ax = (MemberAssignment)x;
141-
var ay = (MemberAssignment)y;
142-
return Visit(ax.Expression, ay.Expression);
143-
case MemberBindingType.MemberBinding:
144-
var mbx = (MemberMemberBinding)x;
145-
var mby = (MemberMemberBinding)y;
146-
return mbx.Bindings.Count==mby.Bindings.Count
147-
&& mbx.Bindings
148-
.Zip(mby.Bindings)
149-
.All(p => self.VisitMemberBinding(p.First, p.Second));
150-
case MemberBindingType.ListBinding:
151-
var mlx = (MemberListBinding)x;
152-
var mly = (MemberListBinding)y;
153-
return mlx.Initializers.Count==mly.Initializers.Count
154-
&& mlx.Initializers
155-
.Zip(mly.Initializers)
156-
.All(p => self.VisitElementInit(p.First, p.Second));
157-
default:
158-
throw new ArgumentOutOfRangeException();
159-
}
160-
}
149+
private bool VisitMemberBinding(MemberBinding x, MemberBinding y) =>
150+
x.BindingType is var bindingType
151+
&& bindingType == y.BindingType
152+
&& x.Member == y.Member
153+
&& bindingType switch {
154+
MemberBindingType.Assignment => Visit(((MemberAssignment) x).Expression, ((MemberAssignment) y).Expression),
155+
MemberBindingType.MemberBinding => MemberBindingsAreEqual(((MemberMemberBinding) x).Bindings, ((MemberMemberBinding) y).Bindings),
156+
MemberBindingType.ListBinding => ElementInitsAreEqual(((MemberListBinding) x).Initializers, ((MemberListBinding) y).Initializers),
157+
_ => throw new ArgumentOutOfRangeException()
158+
};
161159

162160
private bool VisitElementInit(ElementInit x, ElementInit y)
163161
{

0 commit comments

Comments
 (0)