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

时间:2018-11-05 13:33:17

标签: c# dry

我了解为什么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软件包。

1 个答案:

答案 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作为通用参数。