Skip to content

Commit 1fceefd

Browse files
committed
Fix persistent collections' CopyTo implementations
Fixes #1660
1 parent 56d3f3d commit 1fceefd

File tree

7 files changed

+134
-46
lines changed

7 files changed

+134
-46
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using NHibernate.Collection.Generic;
4+
using NUnit.Framework;
5+
6+
namespace NHibernate.Test.CollectionTest
7+
{
8+
[TestFixture]
9+
public class PersistentCollectionsFixture
10+
{
11+
[Test]
12+
public void SelectManyWorksCorrectly()
13+
{
14+
var bags = new IEnumerable<string>[]
15+
{
16+
new List<string> {"A"},
17+
new PersistentGenericBag<string>(null, new[] {"B"}),
18+
new PersistentIdentifierBag<string>(null, new[] {"C"}),
19+
new PersistentGenericList<string>(null, new[] {"D"}),
20+
new PersistentGenericSet<string>(null, new HashSet<string> {"E"})
21+
};
22+
23+
var items = bags.SelectMany(b => b).ToArray();
24+
25+
Assert.That(items, Is.EqualTo(new[] {"A", "B", "C", "D", "E"}));
26+
}
27+
28+
[Test]
29+
public void AddRangeWorksCorrectly()
30+
{
31+
var items = new List<string> {"A"};
32+
items.AddRange(new PersistentGenericBag<string>(null, new[] {"B"}));
33+
items.AddRange(new PersistentIdentifierBag<string>(null, new[] {"C"}));
34+
items.AddRange(new PersistentGenericList<string>(null, new[] {"D"}));
35+
items.AddRange(new PersistentGenericSet<string>(null, new HashSet<string> {"E"}));
36+
37+
Assert.That(items, Is.EqualTo(new[] {"A", "B", "C", "D", "E"}));
38+
}
39+
}
40+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using NHibernate.Collection.Generic;
4+
using NUnit.Framework;
5+
6+
namespace NHibernate.Test.CollectionTest
7+
{
8+
[TestFixture]
9+
public class PersistentGenericMapFixture
10+
{
11+
[Test]
12+
public void SelectManyWorksCorrectly()
13+
{
14+
var bags = new[]
15+
{
16+
new PersistentGenericMap<string, string>(
17+
null,
18+
new Dictionary<string, string> {{"A", "B"}}),
19+
new PersistentGenericMap<string, string>(
20+
null,
21+
new Dictionary<string, string> {{"C", "D"}})
22+
};
23+
24+
var items = bags.SelectMany(b => b).ToArray();
25+
26+
Assert.That(
27+
items,
28+
Is.EquivalentTo(new[] {new KeyValuePair<string, string>("A", "B"), new KeyValuePair<string, string>("C", "D")}));
29+
}
30+
31+
[Test]
32+
public void AddRangeWorksCorrectly()
33+
{
34+
var items = new List<KeyValuePair<string, string>> {new KeyValuePair<string, string>("A", "B")};
35+
36+
items.AddRange(
37+
new PersistentGenericMap<string, string>(
38+
null,
39+
new Dictionary<string, string> {{"C", "D"}}));
40+
41+
Assert.That(
42+
items,
43+
Is.EquivalentTo(new[] {new KeyValuePair<string, string>("A", "B"), new KeyValuePair<string, string>("C", "D")}));
44+
}
45+
}
46+
}

src/NHibernate/Collection/Generic/PersistentGenericBag.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,17 @@ bool ICollection.IsSynchronized
9292
get { return false; }
9393
}
9494

95-
void ICollection.CopyTo(Array array, int index)
95+
void ICollection.CopyTo(Array array, int arrayIndex)
9696
{
97-
for (var i = index; i < Count; i++)
97+
Read();
98+
if (_gbag is ICollection collection)
99+
{
100+
collection.CopyTo(array, arrayIndex);
101+
}
102+
else
98103
{
99-
array.SetValue(this[i], i);
104+
foreach (var item in _gbag)
105+
array.SetValue(item, arrayIndex++);
100106
}
101107
}
102108

@@ -197,16 +203,13 @@ public void Clear()
197203

198204
public bool Contains(T item)
199205
{
200-
var exists = ReadElementExistence(item);
201-
return !exists.HasValue ? _gbag.Contains(item) : exists.Value;
206+
return ReadElementExistence(item) ?? _gbag.Contains(item);
202207
}
203208

204209
public void CopyTo(T[] array, int arrayIndex)
205210
{
206-
for (var i = arrayIndex; i < Count; i++)
207-
{
208-
array.SetValue(this[i], i);
209-
}
211+
Read();
212+
_gbag.CopyTo(array, arrayIndex);
210213
}
211214

212215
public bool Remove(T item)

src/NHibernate/Collection/Generic/PersistentGenericIdentifierBag.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -390,11 +390,17 @@ public int Count
390390
get { return ReadSize() ? CachedSize : _values.Count; }
391391
}
392392

393-
void ICollection.CopyTo(Array array, int index)
393+
void ICollection.CopyTo(Array array, int arrayIndex)
394394
{
395-
for (int i = index; i < Count; i++)
395+
Read();
396+
if (_values is ICollection collection)
397+
{
398+
collection.CopyTo(array, arrayIndex);
399+
}
400+
else
396401
{
397-
array.SetValue(this[i], i);
402+
foreach (var item in _values)
403+
array.SetValue(item, arrayIndex++);
398404
}
399405
}
400406

@@ -449,10 +455,8 @@ public bool Contains(T item)
449455

450456
public void CopyTo(T[] array, int arrayIndex)
451457
{
452-
for (int i = arrayIndex; i < Count; i++)
453-
{
454-
array.SetValue(this[i], i);
455-
}
458+
Read();
459+
_values.CopyTo(array, arrayIndex);
456460
}
457461

458462
public bool Remove(T item)

src/NHibernate/Collection/Generic/PersistentGenericList.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -407,11 +407,17 @@ public T this[int index]
407407

408408
#region ICollection Members
409409

410-
void ICollection.CopyTo(Array array, int index)
410+
void ICollection.CopyTo(Array array, int arrayIndex)
411411
{
412-
for (int i = index; i < Count; i++)
412+
Read();
413+
if (WrappedList is ICollection collection)
414+
{
415+
collection.CopyTo(array, arrayIndex);
416+
}
417+
else
413418
{
414-
array.SetValue(this[i], i);
419+
foreach (var item in WrappedList)
420+
array.SetValue(item, arrayIndex++);
415421
}
416422
}
417423

@@ -450,16 +456,13 @@ public void Add(T item)
450456

451457
public bool Contains(T item)
452458
{
453-
bool? exists = ReadElementExistence(item);
454-
return !exists.HasValue ? WrappedList.Contains(item) : exists.Value;
459+
return ReadElementExistence(item) ?? WrappedList.Contains(item);
455460
}
456461

457462
public void CopyTo(T[] array, int arrayIndex)
458463
{
459-
for (int i = arrayIndex; i < Count; i++)
460-
{
461-
array.SetValue(this[i], i);
462-
}
464+
Read();
465+
WrappedList.CopyTo(array, arrayIndex);
463466
}
464467

465468
bool ICollection<T>.IsReadOnly {

src/NHibernate/Collection/Generic/PersistentGenericMap.cs

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -408,24 +408,8 @@ public bool Contains(KeyValuePair<TKey, TValue> item)
408408

409409
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
410410
{
411-
int c = Count;
412-
var keys = new TKey[c];
413-
var values = new TValue[c];
414-
if (Keys != null)
415-
{
416-
Keys.CopyTo(keys, arrayIndex);
417-
}
418-
if (Values != null)
419-
{
420-
Values.CopyTo(values, arrayIndex);
421-
}
422-
for (int i = arrayIndex; i < c; i++)
423-
{
424-
if (keys[i] != null || values[i] != null)
425-
{
426-
array.SetValue(new KeyValuePair<TKey, TValue>(keys[i], values[i]), i);
427-
}
428-
}
411+
Read();
412+
WrappedMap.CopyTo(array, arrayIndex);
429413
}
430414

431415
public bool Remove(KeyValuePair<TKey, TValue> item)
@@ -453,9 +437,18 @@ public bool IsReadOnly
453437

454438
#region ICollection Members
455439

456-
public void CopyTo(Array array, int index)
440+
public void CopyTo(Array array, int arrayIndex)
457441
{
458-
CopyTo((KeyValuePair<TKey, TValue>[]) array, index);
442+
Read();
443+
if (WrappedMap is ICollection collection)
444+
{
445+
collection.CopyTo(array, arrayIndex);
446+
}
447+
else
448+
{
449+
foreach (var item in WrappedMap)
450+
array.SetValue(item, arrayIndex++);
451+
}
459452
}
460453

461454
public object SyncRoot

src/NHibernate/Collection/Generic/PersistentGenericSet.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,6 @@ public void Clear()
469469

470470
public void CopyTo(T[] array, int arrayIndex)
471471
{
472-
// NH : we really need to initialize the set ?
473472
Read();
474473
WrappedSet.CopyTo(array, arrayIndex);
475474
}

0 commit comments

Comments
 (0)