从静态(非捕获)lambda 返回数据

问题描述 投票:0回答:1

考虑以下方法:

static void Invoke<TArg>(Action<TArg> action, TArg arg) => action(arg);

我知道;看起来没什么用,但它是实际代码的简化。

无论如何,我需要从具有按引用参数的方法调用

Invoke
,并为
action
传递 lambda。我需要某种方法从 lambda 内部返回按引用参数的值。最后,lambda 必须是
static
(非捕获)。

我想出了以下古怪的方案:

static unsafe void UpdateFooAndGetBar(ref object foo, out object bar) {
    var args = (foo, bar: (object)null);
    Invoke(
        static pArgs => {
            ref var args = ref Unsafe.AsRef<(object, object)>(pArgs.ToPointer());
            args.Item1 = 123;
            args.Item2 = "baz";
        },
        new IntPtr(Unsafe.AsPointer(ref args))
    );
    foo = args.foo;
    bar = args.bar;
}

似乎有用,但是

Unsafe
让我紧张。那么,我的代码合法吗?有更好的办法吗?

c# .net unsafe
1个回答
0
投票

假设我们有一个自定义委托,允许按引用使用:

delegate void ActionByRef<T>(ref T value);

然后我们可以在我们的

Invoke
中使用它:

static void Invoke<T>(ActionByRef<T> callback, ref T args)
    => callback(ref args); // TODO any other logic

并使用它没有任何非托管指针:

    public static void UpdateFooAndGetBar(ref object foo, out object bar)
    {
        var args = (foo, bar: (object)null);
        Invoke(
            static (ref (object foo, object bar) args) => {
                args.Item1 = 123;
                args.Item2 = "baz";
            },
            ref args
        );
        foo = args.foo;
        bar = args.bar;
    }

您还可以更进一步,拥有一个符合您确切需求的自定义委托,但这可重用性较差。

© www.soinside.com 2019 - 2024. All rights reserved.