我正在处理一个具有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 asyncAsyncCallback在哪里
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重载,第二个由于不明确的调用而无法编译。
好吧,合乎道理和我对这个界面很满意:
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中,类似的问题已经解决了?
完整的代码可以找到这里。
发布于 2016-01-22 13:38:34
这里没有很好的解决方案;要么方法重载时会出现不明确的调用错误,要么就会有一个全新的API。
就我个人而言,我将添加Func<T, Task>重载并接受中断更改,不再允许方法重载。或者,您可以在新方法(RegisterCallbackEx?)上创建两个重载。并将旧代码标记为Obsolete --这将允许旧代码编译,但鼓励开发人员更改调用。
也许有人能告诉我,在现有的api中,类似的问题已经解决了?
好吧,我可以给你们举个例子,一个类似的问题没有解决。:)
Task.Factory.StartNew通常用于将工作排队到线程池。它是Action-based,我相信它适用于方法组。
当.NET团队想要添加异步支持时,他们引入了一个新的API:Task.Run,它是为Action和Func<Task>重载的。
(请注意,在这种情况下,Task.Run在技术上只支持StartNew使用的一个子集,而StartNew没有标记为Obsolete)。
他们考虑了自己的选择,但这是他们能想到的最好的选择。请注意,仍然存在以下问题,因此,开发人员经常就这两个问题提出问题:
Task.Run不支持方法组。StartNew将在async lambda中编译得很好,但会以令人惊讶的方式运行(由于async void)。由于他们正在改变.NET BCL,所以向后兼容性是最重要的。对于个人库,我更喜欢更安全/更干净的API,而不是严格的向后兼容性,因此在您的情况下,我会做出另一个选择(即添加Func<T, Task>重载作为主要版本升级的一部分)。
发布于 2016-01-22 13:16:30
是否有一种方法来设计这个公共api,以便用户只对一个方法使用空回调,而对另一个方法返回任务。
不,不是真的。问题是Action<T>委托。它允许大量不同的lambda表达式,正如您已经发现的那样。您将在RegisterCallback(Action<T> callback)中遇到的一个主要问题--如果有人像这样使用它:
instance.RegisterCallback<string>(async _ => await Task.Delay(0));他们正在创建一个async void,这是一个巨大的问题。你对Func<T, Task>有了正确的想法。另外,我喜欢您重命名函数并添加“异步”的想法,RegisterAsyncCallback(Func<string, Task> callback)。
https://stackoverflow.com/questions/34947128
复制相似问题