为什么 ReadOnlySpan 不能用作泛型委托和泛型方法的类型参数?
Why ReadOnlySpan may not be used as a type argument for generic delegates and generic methods?
我理解为什么 ReadOnlySpan
不能用作泛型 类 的类型参数。 ReadOnlySpan
只是堆栈,因此它不能用作字段类型,字段成员像它的容器对象一样存在于堆中。但是 return 值和参数始终只是堆栈,那么为什么 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 的 post 说
Let’s consider following C# code:
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);
}
As you can see the non-boxing requirement can not be ensured today if
we allow the Span to be generic type argument. One of the possible
solutions could be to introduce new generic constraint: stackonly. But
then all the managed compilers would have to respect it and ensure the
lack of boxing and other restrictions. This is why it was decided to
simply forbid using Span as a generic argument.
我理解为什么 ReadOnlySpan
不能用作泛型 类 的类型参数。 ReadOnlySpan
只是堆栈,因此它不能用作字段类型,字段成员像它的容器对象一样存在于堆中。但是 return 值和参数始终只是堆栈,那么为什么 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 的 post 说
Let’s consider following C# code:
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); }
As you can see the non-boxing requirement can not be ensured today if we allow the Span to be generic type argument. One of the possible solutions could be to introduce new generic constraint: stackonly. But then all the managed compilers would have to respect it and ensure the lack of boxing and other restrictions. This is why it was decided to simply forbid using Span as a generic argument.