我正在开发一个具有Action<T>
参数的方法的类:
public void RegisterCallback<T> (Action<T> callback);
这很好用。
instance.RegisterCallback<string>(Callback); //method group
instance.RegisterCallback<string>(t => {}); //lambda
现在我想为这个接受async
方法的方法创建一个重载。这样我就可以将它用于任务返回回调并以不同的方式对待它们。
instance.RegisterCallback<string>(AsyncCallback); //method group with async
AsyncCallback
private Task AsyncCallback(string s)
{
return Task.Delay(0);
}
天真的方法是采用这样的方法:
void RegisterCallback<T>(Func<T, Type> callback);
但它存在一些问题:
//1
instance.RegisterCallback<string>(async t => await Task.Delay(0));
//2
instance.RegisterCallback<string>(AsyncCallback); //method group with async
第一个被解析为Action<T> callback
重载,第二个由于模糊调用而无法编译。
那么,makes sense我对这个界面很满意:
void RegisterAsyncCallback<T>(Func<T, Task> callback);
但是这两个调用编译没有问题:
instance.RegisterCallback<string>(async t => await Task.Delay(0));
instance.RegisterAsyncCallback<string>(async t => await Task.Delay(0));
有没有办法设计这个公共api,以便用户只使用void
回调一个方法,而任务返回另一个方法。
也许有人可以指出我现有的api,类似的问题已经解决了?
可以找到完整的代码here。
答案 0 :(得分:3)
这里没有好的解决方案;你可能会遇到方法重载的模糊调用错误,或者你会有一个全新的API。
就个人而言,我会添加Func<T, Task>
重载并进行重大更改,不再允许方法重载。或者,您可以在新方法(RegisterCallbackEx
?)上创建两个重载并将旧方法标记为Obsolete
- 这将允许旧代码编译,但鼓励开发人员更改调用。
也许有人可以指出我现有的api,类似的问题已经解决了?
好吧,我可以举个例子解决类似问题 的问题。 :)
Task.Factory.StartNew
通常用于将工作排队到线程池。这是基于Action
的,我相信它适用于方法组。
当.NET团队想要添加异步支持时,他们引入了一个新的API:Task.Run
,它为Action
和Func<Task>
重载。
(请注意,在这种情况下,Task.Run
在技术上仅支持StartNew
次使用的子集,而StartNew
未标记为Obsolete
。
他们考虑了他们的选择,但这是他们想出的最好的选择。请注意,以下问题仍然存在,开发人员在SO上定期提出有关这两点的问题:
Task.Run
不支持方法组。StartNew
将使用async
lambdas编译得很好,但会以令人惊讶的方式运行(由于async void
)。由于他们正在改变.NET BCL,因此向后兼容性至关重要。对于个人库,我更喜欢更安全/更干净的API而不是严格的向后兼容性,因此我会在您的情况下做出另一种选择(即,只需添加Func<T, Task>
重载作为主要版本升级的一部分。)
答案 1 :(得分:2)
有没有办法设计这个公共api,以便用户只使用一个方法的void回调和另一个方法返回的任务。
不,不是真的。问题是Action<T>
代表。它允许您已经发现的大量各种lambda表达式。您将遇到RegisterCallback(Action<T> callback)
的一个主要问题 - 如果有人像这样使用它:
instance.RegisterCallback<string>(async _ => await Task.Delay(0));
他们正在创建async void
,这是一个很大的问题。你对Func<T, Task>
有了正确的想法。另外,我喜欢你的想法,重命名该功能并添加&#34; Async&#34;似乎合适,RegisterAsyncCallback(Func<string, Task> callback)
。