为什么ReadOnlySpan不能用作泛型委托和泛型方法的类型参数



我理解为什么ReadOnlySpan不能用作泛型类的类型参数。ReadOnlySpan仅是堆栈,因此不能用作字段类型,字段成员像它的容器对象一样生活在堆中。但是,返回值和参数总是仅堆栈的,那么为什么ReadOnlySpan不能用作泛型委托和泛型方法的类型参数呢?

这里有一个例子来说明我的意思:

using System;
namespace ConsoleApp7
{
class Program
{
public delegate TResult MyFunc<TResult>(ReadOnlySpan<char> arg);
static int GetSpanLength(ReadOnlySpan<char> span)
{
return span.Length;
}
static void Main(string[] args)
{
var span = "hello".AsSpan();
MyFunc<int> func1 = GetSpanLength;
var result1 = DoSomething(func1, span);
// The type 'ReadOnlySpan<char>' may not be used as a type argument
Func<ReadOnlySpan<char>, int> func2 = GetSpanLength;
//The type 'ReadOnlySpan<char>' may not be used as a type argument
var result = DoSomething<int, ReadOnlySpan<char>>(func2, span);

}
static TResult DoSomething<TResult, T>(Func<T, TResult> func, T arg)
{
return func(arg);
}
static TResult DoSomething<TResult>(MyFunc<TResult> func, ReadOnlySpan<char> arg)
{
return func(arg);
}
}
}

这非常不幸,因为它迫使我有两个相同版本的DoSomething方法,使我的代码非常WET。

注意:对于以.NET Framework为目标的项目,您需要安装System.Memory Nuget包。

Adam Sitnik的这篇文章说

让我们考虑以下C#代码:

Span<byte> Allocate() => new Span<byte>(new byte[256]);
void CallAndPrint<T>(Func<T> valueProvider) // no generic requirements for T
{
object value = valueProvider.Invoke(); // boxing!
Console.WriteLine(value.ToString());
}
void Demo()
{
Func<Span<byte>> spanProvider = Allocate;
CallAndPrint<Span<byte>>(spanProvider);
}

正如你所看到的,如果我们允许Span是泛型类型参数。可能的解决方案可能是引入新的通用约束:stackonly。但是那么所有托管编译器都必须尊重它,并确保缺少拳击和其他限制。这就是为什么决定简单地禁止将Span用作泛型参数。

最新更新