如何解决不能在lambda中使用refs的问题
本文关键字:refs 问题 何解 决不能 lambda | 更新日期: 2023-09-27 18:26:28
我正在为一些C代码编写一个包装器,如果不能在lambda中使用ref
关键字,我就不太清楚如何编写这一位。
非托管函数包装器如下所示:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate int SDL_EventFilter(ref object userData, ref SDL_Event @event);
[DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_AddEventWatch")]
internal static extern void SDL_AddEventWatch(SDL_EventFilter filter, ref object userData);
但我不想直接使用SDL_Event
(它是一个复杂的结构),所以我将它封装在自己的类Event
中。然而,C期望一个指向SDL_Event
而不是Event
的指针,所以我必须再写一些代码来完成这一切:
public delegate void EventFilter(object userData, Event @event);
public static void AddEventWatch(EventFilter filter, object userData)
{
SDL_AddEventWatch((ref data, ref e) => // <-- can't do this
{
filter(data, new Event(ref e));
return 0;
}, ref userData);
}
这基本上取了我得到的SDL_Event
,并将其转换为我的Event
类。然而,我不能在lambda中使用ref
关键字,但我不知道如何绕过它
我可以定义一个常规的helper方法,而不是使用lambda,但我需要在其中使用本地filter
变量,而且我不知道如何在不更改签名的情况下将其输入函数中(这样它就不匹配SDL_EventFilter
)。
在JavaScript、PHP或Python中,我可以构造一个可调用的对象,使filter
成为成员变量,然后使用该对象作为回调。我不确定C#中是否有类似的概念,是吗?
使用ref
关键字时,还必须给定类型。像这样:
(ref object data, ref SDL_Event e) => { ... }
lambda的参数列表类似于普通命名方法的参数列表。但是,在lambda中可以省略这些类型,但前提是没有参数具有修饰符(如ref
、out
、params
)。
是的,您不能这样做,因为Lambda
实际上捕获了CompilerGenerated
类中的变量并重用它。
我们可以在传递给方法时使用ref
关键字,但如果您将参数捕获到其他变量It wont behave as you expect
,则仍然可以。
因此,简单的解决方法是创建一个方法并使用,而不是lambda。
类似的东西(未经测试):
class Capture
{
private readonly EventFilter filter;
public Capture(EventFilter filter)
{
this.filter = filter;
}
public int Method(ref object userData, ref SDL_Event @event)
{
this.filter(userData, new Event(ref event));
return 0;
}
}
public static void AddEventWatch(EventFilter filter, object userData)
{
var capture = new Capture(filter);
SDL_AddEventWatch(capture.Method, ref userData);
}