C# 跟踪行动<;T>;lambdas as Action<;对象>;
过去提出的类似问题:C# 跟踪行动<;T>;lambdas as Action<;对象>;,c#,generics,delegates,C#,Generics,Delegates,过去提出的类似问题: 所有人都找到了将动作myActionT包装成匿名新动作(o=>myActionT((T)o))的解决方案 我的用例是,初始的、类型化的lambda是一个数据订阅回调,将其包装成匿名回调意味着我无法使用原始的操作取消订阅 我把范围缩小到这个样板示例: internal class Demo { public class Dispatcher { private List<Action<
动作myActionT
包装成匿名新动作(o=>myActionT((T)o))的解决方案代码>
我的用例是,初始的、类型化的lambda是一个数据订阅回调,将其包装成匿名回调意味着我无法使用原始的操作取消订阅
我把范围缩小到这个样板示例:
internal class Demo
{
public class Dispatcher
{
private List<Action<object>> callbacks = new List<Action<object>>();
public void Subscribe<T>(Action<T> cbk)
{
callbacks.Add(cbk); // <- compile error, Action<T> is contravariant
}
public void Unsubscribe<T>(Action<T> cbck)
{
callbacks.Remove(cbck); // <- compile error
}
}
private static void Handler(int v) {}
private static void Handler(string v) {}
public static void Main()
{
var dispatcher = new Dispatcher();
dispatcher.Subscribe<int>(Handler);
dispatcher.Subscribe<string>(Handler);
dispatcher.Unsubscribe<int>(Handler);
}
}
我觉得目前的方法(函数指针/委托、跟踪订阅类型)让我陷入了困境
但是我没有找到一个更直接的方法来实现这一点(除了用我需要的类型重载Subscribe
,这可能是明智的选择)它非常简单。请尝试以下方法:
private List<Delegate> callbacks = new List<Delegate>();
然后,您不需要取消订阅
方法-这将要求您保留对操作cbk
的引用。您只需对订阅调用.Dispose()
请尝试以下代码:
internal class Demo
{
public class Dispatcher
{
private List<Delegate> callbacks = new List<Delegate>();
public IDisposable Subscribe<T>(Action<T> cbk)
{
callbacks.Add(cbk);
return new AnonymousDisposable(() => callbacks.Remove(cbk));
}
}
private static void Handler(int v) { }
private static void Handler(string v) { }
public static void Main()
{
var dispatcher = new Dispatcher();
var subscription = dispatcher.Subscribe<int>(Handler);
dispatcher.Subscribe<string>(Handler);
subscription.Dispose();
}
}
public sealed class AnonymousDisposable : IDisposable
{
private readonly Action _action;
private int _disposed;
public AnonymousDisposable(Action action)
{
_action = action;
}
public void Dispose()
{
if (Interlocked.Exchange(ref _disposed, 1) == 0)
{
_action();
}
}
}
内部类演示
{
公共类调度器
{
私有列表回调=新列表();
公共IDisposable订阅(操作cbk)
{
callbacks.Add(cbk);
返回新的匿名(()=>callbacks.Remove(cbk));
}
}
私有静态无效处理程序(int v){}
私有静态无效处理程序(字符串v){}
公共静态void Main()
{
var dispatcher=newdispatcher();
var subscription=dispatcher.subscripte(处理程序);
dispatcher.Subscribe(处理程序);
subscription.Dispose();
}
}
公开密封类:IDisposable
{
私有只读操作\u操作;
私人INTU;
公众匿名(行动)
{
_行动=行动;
}
公共空间处置()
{
if(联锁交换(参考_,1)==0)
{
_动作();
}
}
}
“因为我实际上只需要值类型”<代码>字符串
不是值类型。除订阅/取消订阅外,您还计划如何处理回调
。你也研究过了吗?我添加了一些关于我如何使用回调的详细信息
@AlinMotogna-你考虑过使用微软的Rx吗?直到现在才听说过,对于我的简单用例来说,它看起来很重,但我一定会研究它。谢谢
IDisposable Subscribe<T>(Action<T> cbk)
internal class Demo
{
public class Dispatcher
{
private List<Delegate> callbacks = new List<Delegate>();
public IDisposable Subscribe<T>(Action<T> cbk)
{
callbacks.Add(cbk);
return new AnonymousDisposable(() => callbacks.Remove(cbk));
}
}
private static void Handler(int v) { }
private static void Handler(string v) { }
public static void Main()
{
var dispatcher = new Dispatcher();
var subscription = dispatcher.Subscribe<int>(Handler);
dispatcher.Subscribe<string>(Handler);
subscription.Dispose();
}
}
public sealed class AnonymousDisposable : IDisposable
{
private readonly Action _action;
private int _disposed;
public AnonymousDisposable(Action action)
{
_action = action;
}
public void Dispose()
{
if (Interlocked.Exchange(ref _disposed, 1) == 0)
{
_action();
}
}
}