Browse Source

Merge pull request #4695 from AvaloniaUI/fixes/avalonialist-copyto

Fix AvaloniaList's ICollection.CopyTo implementation
pull/4700/head
danwalmsley 5 years ago
committed by GitHub
parent
commit
8d1f7a71e0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .ncrunch/Avalonia.Controls.UnitTests.net47.v3.ncrunchproject
  2. 68
      src/Avalonia.Base/Collections/AvaloniaList.cs
  3. 23
      tests/Avalonia.Base.UnitTests/Collections/AvaloniaListTests.cs

1
.ncrunch/Avalonia.Controls.UnitTests.net47.v3.ncrunchproject

@ -3,5 +3,6 @@
<HiddenComponentWarnings>
<Value>MissingOrIgnoredProjectReference</Value>
</HiddenComponentWarnings>
<FixtureName>Avalonia.Controls.UnitTests.TimePickerTests</FixtureName>
</Settings>
</ProjectConfiguration>

68
src/Avalonia.Base/Collections/AvaloniaList.cs

@ -543,7 +543,73 @@ namespace Avalonia.Collections
/// <inheritdoc/>
void ICollection.CopyTo(Array array, int index)
{
_inner.CopyTo((T[])array, index);
if (array == null)
{
throw new ArgumentNullException(nameof(array));
}
if (array.Rank != 1)
{
throw new ArgumentException("Multi-dimensional arrays are not supported.");
}
if (array.GetLowerBound(0) != 0)
{
throw new ArgumentException("Non-zero lower bounds are not supported.");
}
if (index < 0)
{
throw new ArgumentException("Invalid index.");
}
if (array.Length - index < Count)
{
throw new ArgumentException("The target array is too small.");
}
if (array is T[] tArray)
{
_inner.CopyTo(tArray, index);
}
else
{
//
// Catch the obvious case assignment will fail.
// We can't find all possible problems by doing the check though.
// For example, if the element type of the Array is derived from T,
// we can't figure out if we can successfully copy the element beforehand.
//
Type targetType = array.GetType().GetElementType()!;
Type sourceType = typeof(T);
if (!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType)))
{
throw new ArgumentException("Invalid array type");
}
//
// We can't cast array of value type to object[], so we don't support
// widening of primitive types here.
//
object[] objects = array as object[];
if (objects == null)
{
throw new ArgumentException("Invalid array type");
}
int count = _inner.Count;
try
{
for (int i = 0; i < count; i++)
{
objects[index++] = _inner[i];
}
}
catch (ArrayTypeMismatchException)
{
throw new ArgumentException("Invalid array type");
}
}
}
/// <inheritdoc/>

23
tests/Avalonia.Base.UnitTests/Collections/AvaloniaListTests.cs

@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
@ -334,5 +335,27 @@ namespace Avalonia.Base.UnitTests.Collections
Assert.True(raised);
}
[Fact]
public void Can_CopyTo_Array_Of_Same_Type()
{
var target = new AvaloniaList<string> { "foo", "bar", "baz" };
var result = new string[3];
target.CopyTo(result, 0);
Assert.Equal(target, result);
}
[Fact]
public void Can_CopyTo_Array_Of_Base_Type()
{
var target = new AvaloniaList<string> { "foo", "bar", "baz" };
var result = new object[3];
((IList)target).CopyTo(result, 0);
Assert.Equal(target, result);
}
}
}

Loading…
Cancel
Save