Skip to content

Commit ed07ed4

Browse files
DmitryNaumovhazzik
authored andcommitted
Improve Tuple equality
Let's make clear statement that Tuple can't have null Items and Items can't change (as well as Tuple's hash code)
1 parent fd08421 commit ed07ed4

File tree

3 files changed

+34
-15
lines changed

3 files changed

+34
-15
lines changed

src/NHibernate/Linq/NestedSelects/NestedSelectRewriter.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,7 @@ private static LambdaExpression MakePredicate(int index)
199199
Expression.Call(typeof(object),
200200
"ReferenceEquals",
201201
System.Type.EmptyTypes,
202-
Expression.ArrayIndex(
203-
Expression.MakeMemberAccess(t, Tuple.ItemsField),
204-
Expression.Constant(index)),
202+
ArrayIndex(Expression.Property(t, Tuple.ItemsProperty), index),
205203
Expression.Constant(null))),
206204
t);
207205
}
@@ -221,18 +219,16 @@ private static LambdaExpression CreateSelector(IEnumerable<ExpressionHolder> exp
221219

222220
var initializers = expressions.Select((x, index) => new { x.Tuple, index })
223221
.Where(x => x.Tuple == tuple)
224-
.Select(x => ArrayIndex(x.index, parameter));
222+
.Select(x => ArrayIndex(parameter, x.index));
225223

226224
var newArrayInit = Expression.NewArrayInit(typeof(object), initializers);
227225

228226
return Expression.Lambda(
229-
Expression.MemberInit(
230-
Expression.New(typeof(Tuple)),
231-
Expression.Bind(Tuple.ItemsField, newArrayInit)),
227+
Expression.New(Tuple.Constructor, newArrayInit),
232228
parameter);
233229
}
234230

235-
private static Expression ArrayIndex(int value, Expression param)
231+
private static Expression ArrayIndex(Expression param, int value)
236232
{
237233
return Expression.ArrayIndex(param, Expression.Constant(value));
238234
}

src/NHibernate/Linq/NestedSelects/SelectClauseRewriter.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ private Expression AddAndConvertExpression(Expression expression)
5454

5555
return Expression.Convert(
5656
Expression.ArrayIndex(
57-
Expression.MakeMemberAccess(parameter,
58-
Tuple.ItemsField),
57+
Expression.Property(parameter, Tuple.ItemsProperty),
5958
Expression.Constant(expressions.Count - 1)),
6059
expression.Type);
6160
}

src/NHibernate/Linq/NestedSelects/Tuple.cs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,30 @@ namespace NHibernate.Linq.NestedSelects
66
{
77
internal class Tuple : IEquatable<Tuple>
88
{
9-
public static readonly FieldInfo ItemsField = typeof (Tuple).GetField("Items");
9+
public static readonly ConstructorInfo Constructor = typeof (Tuple).GetConstructor(new[] { typeof (object[]) });
10+
public static readonly PropertyInfo ItemsProperty = typeof (Tuple).GetProperty("Items");
11+
private readonly object[] _items;
1012

11-
public object[] Items;
13+
public Tuple(object[] items)
14+
{
15+
if (items == null) throw new ArgumentNullException("items");
16+
_items = items;
17+
}
18+
19+
public object[] Items
20+
{
21+
get { return _items; }
22+
}
1223

1324
public bool Equals(Tuple other)
1425
{
1526
if (other == null) return false;
27+
if (ReferenceEquals(this, other)) return true;
1628

17-
if (other.Items.Length != Items.Length)
29+
if (other._items.Length != _items.Length)
1830
return false;
1931

20-
return !other.Items.Where((t, index) => !Equals(t, Items[index])).Any();
32+
return _items.SequenceEqual(other._items);
2133
}
2234

2335
public override bool Equals(object obj)
@@ -27,7 +39,19 @@ public override bool Equals(object obj)
2739

2840
public override int GetHashCode()
2941
{
30-
return (Items != null ? Items.Length.GetHashCode() : 0);
42+
unchecked
43+
{
44+
var length = _items.Length;
45+
if (length == 0)
46+
return 0;
47+
48+
var lengthCode = length;
49+
var firstElement = _items[0];
50+
if (ReferenceEquals(firstElement, null))
51+
return lengthCode;
52+
53+
return firstElement.GetHashCode() * 397 ^ lengthCode;
54+
}
3155
}
3256
}
3357
}

0 commit comments

Comments
 (0)