Sergio0694/PolySharp

Add optional polyfill (alias) to support getsubarray

arcutright opened this issue · 1 comments

Rationale

Slicing arrays is a fairly common task, and a workaround is simple.

Proposed API

Optional property flag in .csproj to alias System.Runtime.CompilerServices.RuntimeHelpers

<PolySharpAliasRuntimeHelpers>true</PolySharpAliasRuntimeHelpers>

Drawbacks

Obvious, see previous discussion in #8

Alternatives

Not sure there's any other way to support modern C# range syntax for arrays and spans.

Proposed hack

minimal example, excluding everything else from RuntimeHelpers

public static partial class RuntimeHelpers {
  // runtime support for range operator eg `myarray[0..5]`
  public static T[] GetSubArray<T>(T[] array, System.Range range) {
    var (offset, length) = range.GetOffsetAndLength(array.Length);
    if (length == 0)
      return Array.Empty<T>();

    T[] dest;
    if (typeof(T).IsValueType || typeof(T[]) == array.GetType()) {
      // We know the type of the array to be exactly T[] or an array variance
      // compatible value type substitution like int[] <-> uint[].
      if (length == 0)
        return Array.Empty<T>();

      dest = new T[length];
    }
    else {
      // The array is actually a U[] where U:T. We'll make sure to create
      // an array of the exact same backing type. The cast to T[] will
      // never fail.
      dest = (T[])(Array.CreateInstance(array.GetType().GetElementType(), length));
    }

    Array.Copy(array, offset, dest, 0, length);
    return dest;
  }
}

"Not sure there's any other way to support modern C# range syntax for arrays and spans."

The issue is just for arrays, not spans. Slicing spans with the built-in syntax already works perfectly fine, as it doesn't require the runtime helper method. And slicing arrays is something that one shouldn't really do much at all if possible anyway. I don't think it's worth the extra complexity, also so far I've tried to avoid polyfilling methods to avoid things getting too out of hand 🙂