为什么调用采用 Span<T> 和 T[] 的泛型方法无法推断类型参数?

Why calling a generic method that takes Span<T> with T[] cannot infer a type argument?

我创建了一个将 Span<T>/ReadOnlySpan<T> 作为参数的通用方法。

我想用一个数组调用我的方法,但这是一个错误。 (代码示例中的错误 CS0411,int b。)

我认为编译器在没有类型参数的情况下将 Array 转换为 Span,因为存在从 T[]Span<T>/ReadOnlySpan<T> 的隐式转换,但事实并非如此。为什么?

int[] items = { 1, 2, 3 };

int a = Random.Shared.NextItem(items);
// -> what I want that implicit conversion happens but this is not generic.

int b = Random.Shared.NextItemGeneric(items);
// -> error CS0411: The type arguments for method 'RandomExtensions.NextItemGeneric<T>(Random, ReadOnlySpan<T>)'
// cannot be inferred from the usage. Try specifying the type arguments explicitly.

int c = Random.Shared.NextItemGeneric<int>(items);
// -> ok

internal static class RandomExtensions {
    public static int NextItem(this Random random, ReadOnlySpan<int> items) {
        return items[random.Next(items.Length)];
    }

    public static T NextItemGeneric<T>(this Random random, ReadOnlySpan<T> items) {
        return items[random.Next(items.Length)];
    }
}

我将此作为答案发布,但这是我的有根据的猜测,而不是实际知识。

我假设这是因为,虽然存在从 T[]ReadOnlySpan<T> 的隐式转换,但编译器看不到它,因为它不知道 T 是什么是因为它没有 ReadOnlySpan<T> 来推断它。这可能是先有鸡还是先有蛋的情况,即在不知道 T 的情况下无法获得 ReadOnlySpan<T>,但在不知道 ReadOnlySpan<T> 的情况下无法获得 T。第一个和最后一个调用有效,因为这两件事中只有一个是未知的,但在第二个调用中两者都是未知的,所以你运气不好。您要么必须指定通用类型,要么创建您自己的 ReadOnlySpan<T>.