c# - 具有 in 修饰符的事件参数的 Observable.FromEvent 会导致异常

标签 c# system.reactive

我正在使用一个第三方库,它有一个事件\事件处理程序,我想将其转换为 一个可观察的。事件处理程序委托(delegate)需要一个带有 in 关键字的结构。这会导致异常:

System.ArgumentException - 无法绑定(bind)到目标方法,因为其签名与委托(delegate)类型的签名不兼容。

来自

System.Private.CoreLib.dll!System.Reflection.RuntimeMethodInfo.CreateDelegateInternal(System.Type delegateType, object firstArgument, System.DelegateBindingFlags bindingFlags) Line 556    C#
    System.Private.CoreLib.dll!System.Reflection.RuntimeMethodInfo.CreateDelegate(System.Type delegateType, object target) Line 534 C#
    System.Reactive.dll!System.Reactive.ReflectionUtils.CreateDelegate<Test.TheDelegate>(object o, System.Reflection.MethodInfo method) Line 18 C#

如果我从参数中删除 in,它会按预期工作。 我不明白为什么?甚至可以做到吗?

using System;
using System.Diagnostics;
using System.Reactive.Linq;

Test test = new();

Start();
test.TriggerEvent();
test.TriggerEvent();

void Start()
{
    Debug.WriteLine("Start");
    var o = Observable.FromEvent<Test.TheDelegate, SomeStruct>
        (h => test.TheEvent += h, 
         h => test.TheEvent -= h)
                      .Subscribe(OnNext);
}

void OnNext(SomeStruct s) => Debug.WriteLine("OnNext");

public class Test
{
    public delegate void TheDelegate(in SomeStruct o);

    // Without the in (or ref) keyword, no exception
    //public delegate void TheDelegate(SomeStruct o);

    public event TheDelegate? TheEvent;

    public void TriggerEvent()
    {
        SomeStruct s = new();
        TheEvent?.Invoke(s);
        Debug.WriteLine("Event Fired");
    }
}

public struct SomeStruct
{ }

最佳答案

我能够重现ArgumentException在运行时。要解决这个问题,您可以使用 Observable.FromEvent具有额外 conversion 的过载参数:

public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(
    Func<Action<TEventArgs>, TDelegate> conversion,
    Action<TDelegate> addHandler,
    Action<TDelegate> removeHandler);

用法:

var observable = Observable.FromEvent<Test.TheDelegate, SomeStruct>
(
    action => (in SomeStruct arg) => action(arg),
    h => test.TheEvent += h,
    h => test.TheEvent -= h
);
var subscription = observable.Subscribe(OnNext);

conversion转换 Action<SomeStruct>Test.TheDelegate 。与更简单的重载相反,转换的有效性是在编译时检查的。

关于c# - 具有 in 修饰符的事件参数的 Observable.FromEvent 会导致异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72665837/

相关文章:

c# - Web API发布返回415-不支持的媒体类型

c# - 如何将组合框的数据表示为整数

c# - 可从链式任务中观察到

c# - "await/async": Why the 2 pieces of code doesn't run the same?

c# - 异步方法中的 Await 与 Task.Result

system.reactive - 验证用户是否从具有响应式扩展的响应式列表中键入了单词

system.reactive - RxJs——每次事件爆发后重播所有事件

c# - 接收 : Ignoring updates caused by Subscribers

c# - 根据值限制 IObservable

c# - 将节点添加到 treeView 中的特定父节点 (c#)