Skip to content

Commit a004318

Browse files
committed
Support copying elements from list to array with compatible types.
1 parent 4516408 commit a004318

File tree

5 files changed

+57
-5
lines changed

5 files changed

+57
-5
lines changed

Core/Collections/FilteredObservableList.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,23 @@ void Rebuild()
339339
void IList.Clear() => throw new InvalidOperationException();
340340
void ICollection<T>.Clear() => throw new InvalidOperationException();
341341
bool IList.Contains(object? value) => value is T item && this.Contains(item);
342-
void ICollection.CopyTo(System.Array array, int index) => this.CopyTo((T[])array, index);
342+
void ICollection.CopyTo(System.Array array, int index)
343+
{
344+
if (array is T[] targetArray)
345+
this.CopyTo(targetArray, index);
346+
else if (array.GetType().GetElementType()!.IsAssignableFrom(typeof(T)))
347+
{
348+
var count = this.items.Count;
349+
if (count == 0)
350+
return;
351+
if (index < 0 || (index + count) > array.Length)
352+
throw new ArgumentOutOfRangeException(nameof(index));
353+
for (var i = 0; i < count; ++i)
354+
array.SetValue(this.items[i].Item1, index++);
355+
}
356+
else
357+
throw new ArgumentException($"Type of array element {array.GetType().GetElementType()!.Name} is not parent type of {typeof(T).Name}.");
358+
}
343359
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
344360
int IList.IndexOf(object? value) => value is T item ? this.IndexOf(item) : -1;
345361
void IList.Insert(int index, object? value) => throw new InvalidOperationException();

Core/Collections/ObservableList.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,13 @@ static IList ToIList(IEnumerable<T> elements)
376376

377377
// Interface implementations.
378378
void ICollection<T>.Add(T value) => this.Add(value);
379-
void ICollection.CopyTo(Array array, int index) => this.CopyTo((T[])array, index);
379+
void ICollection.CopyTo(Array array, int index)
380+
{
381+
if (array is T[] targetArray)
382+
this.list.CopyTo(targetArray, index);
383+
else
384+
((ICollection)this.list).CopyTo(array, index);
385+
}
380386
bool ICollection<T>.IsReadOnly => false;
381387
bool ICollection.IsSynchronized => false;
382388
object ICollection.SyncRoot => this;

Core/Collections/ReadOnlyObservableList.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,25 @@ public ReadOnlyObservableList(IList<T> source)
9393
// Interface implementations.
9494
void ICollection<T>.Add(T value) => throw new InvalidOperationException();
9595
void ICollection<T>.Clear() => throw new InvalidOperationException();
96-
void ICollection.CopyTo(Array array, int index) => this.CopyTo((T[])array, index);
96+
void ICollection.CopyTo(Array array, int index)
97+
{
98+
if (array is T[] targetArray)
99+
this.sourceList.CopyTo(targetArray, index);
100+
else if (this.sourceList is ICollection collection)
101+
collection.CopyTo(array, index);
102+
else if (array.GetType().GetElementType()!.IsAssignableFrom(typeof(T)))
103+
{
104+
var count = this.sourceList.Count;
105+
if (count == 0)
106+
return;
107+
if (index < 0 || (index + count) > array.Length)
108+
throw new ArgumentOutOfRangeException(nameof(index));
109+
for (var i = 0; i < count; ++i)
110+
array.SetValue(this.sourceList[i], index++);
111+
}
112+
else
113+
throw new ArgumentException($"Type of array element {array.GetType().GetElementType()!.Name} is not parent type of {typeof(T).Name}.");
114+
}
97115
bool ICollection<T>.IsReadOnly => true;
98116
bool ICollection.IsSynchronized => (this.sourceList as ICollection)?.IsSynchronized ?? false;
99117
bool ICollection<T>.Remove(T item) => throw new InvalidOperationException();

Core/Collections/SortedObservableList.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,13 @@ public bool SortAt(int index)
590590

591591
// Interface implementations.
592592
void ICollection<T>.Add(T value) => this.Add(value);
593-
void ICollection.CopyTo(Array array, int index) => this.CopyTo((T[])array, index);
593+
void ICollection.CopyTo(Array array, int index)
594+
{
595+
if (array is T[] targetArray)
596+
this.list.CopyTo(targetArray, index);
597+
else
598+
((ICollection)this.list).CopyTo(array, index);
599+
}
594600
bool ICollection<T>.IsReadOnly => false;
595601
bool ICollection.IsSynchronized => false;
596602
object ICollection.SyncRoot => this;

Core/Collections/TypeConvertedObservableList.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,13 @@ void RebuildList()
243243
// Interface implementations.
244244
void ICollection<TDest>.Add(TDest value) => throw new InvalidOperationException();
245245
void ICollection<TDest>.Clear() => throw new InvalidOperationException();
246-
void ICollection.CopyTo(Array array, int index) => this.CopyTo((TDest[])array, index);
246+
void ICollection.CopyTo(Array array, int index)
247+
{
248+
if (array is TDest[] targetArray)
249+
this.list.CopyTo(targetArray, index);
250+
else
251+
((ICollection)this.list).CopyTo(array, index);
252+
}
247253
bool ICollection<TDest>.IsReadOnly => true;
248254
bool ICollection.IsSynchronized => (this.sourceList as ICollection)?.IsSynchronized ?? false;
249255
bool ICollection<TDest>.Remove(TDest item) => throw new InvalidOperationException();

0 commit comments

Comments
 (0)