我了解为什么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方法,这使我的代码变得很湿。
注意:对于面向.NET Framework的项目,您需要安装System.Memory Nuget软件包。
答案 0 :(得分:5)
亚当·锡特尼克(Adam Sitnik)的这个post说
让我们考虑以下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作为通用参数。