Search code examples
c#.net-core.net-5

.AsSpan ArrayTypeMismatchException


can smebody explain why .AsSpan thorws an ArrayTypeMismatchException while creating a new ReadOnlySpan doesn't?

SomeMethod(Foo data) {
  IPoint[] tmp = (IPoint[])data.Points; // data.Points is OwnPoint[] (class OwnPoint : IPoint)
  //ReadOnlySpan<IPoint> pointsSpan = ((IPoint[])tmp).AsSpan(); //  System.ArrayTypeMismatchException: 'Attempted to access an element as a type incompatible with the array.'
  //ReadOnlySpan<IPoint> pointsSpan = tmp.AsSpan(); //  System.ArrayTypeMismatchException: 'Attempted to access an element as a type incompatible with the array.'
  ReadOnlySpan<IPoint> pointsSpan = new ReadOnlySpan<IPoint>(tmp);// works
  Bar(pointsSpan);
}

public void Bar(ReadOnlySpan<IPoint> pts) {
    // ...
}

what am I missing? thought that .AsSpan did the same as creating a new one.


Solution

  • It's a question of type safety. As pointed by @canton7 Span<T> have check against type, while ReadOnlySpan<T> doesn't. First one is mutable and it's possible to assign some value to it. As long value have same type, everything is ok, but if value have different type (e.g. ((object[])new string[1])[0] = 1) array assignment throws ArrayTypeMismatchException so it won't be possible to have values of different types inside array.

    Span<T> does this check at instantiation time. I don't know motivation behind this, maybe it's performance.

    ReadOnlySpan<T> doesn't need this check since it's not mutable.

    You can read more about array casting in chapter 16 "Arrays" in Clr via C# by Jeffrey Richter