代码之家  ›  专栏  ›  技术社区  ›  Joannes Vermorel Jonathan McIntire

如何使用Linq表达式树从Span<T>中获取值?

  •  11
  • Joannes Vermorel Jonathan McIntire  · 技术社区  · 6 年前

    我想用Linq表达式树来调用 Span<T>

    var spanGetter = typeof(Span<>)
        .MakeGenericType(typeof(float)).GetMethod("get_Item");
    
    var myFloatSpan = Expression.Parameter(typeof(Span<float>), "s");
    
    var myValue = Expression.Call(
        myFloatSpan,
        spanGetter,
        Expression.Constant(42));
    
    var myAdd = Expression.Add(
        myValue,
        Expression.Constant(13f));    
    

    myValue 属于类型 Single& (又名 ref struct Single (又名 struct ).

    Span<T>

    1 回复  |  直到 6 年前
        1
  •  7
  •   Simon Mourier    6 年前

    我有一个解决方案,但远不是理想的,你会看到的。我们重新使用C#语法糖引擎。

    class Program
    {
        static void Main(string[] args)
        {
            var spanGetter = typeof(Program).GetMethod("GetItem").MakeGenericMethod(typeof(float));
    
            var myFloatSpan = Expression.Parameter(typeof(Span<float>), "s");
    
            var myValue = Expression.Call(
                null,
                spanGetter,
                myFloatSpan,
                Expression.Constant(42));
    
            var myAdd = Expression.Add(
                myValue,
                Expression.Constant(13f));
    
            var expr = Expression.Lambda<MyFunc>(myAdd, myFloatSpan).Compile();
    
            var span = new Span<float>(new float[43]);
            span[42] = 12.3456f;
            Console.WriteLine(expr(span)); // -> 25.3456
        }
    
        // hopefully, this shouldn't be too bad in terms of performance...
        // C# knows how to do compile this, while Linq Expressions doesn't
        public static T GetItem<T>(Span<T> span, int index) => span[index];
    
        // we need that because we can't use a Span<T> directly with Func<T>
        // we could make it generic also I guess
        public delegate float MyFunc(Span<float> span);
    }