首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >区分空法和任务返回法

区分空法和任务返回法
EN

Stack Overflow用户
提问于 2016-01-22 12:48:37
回答 2查看 111关注 0票数 3

我正在处理一个具有Action<T>参数的方法的类:

代码语言:javascript
复制
public void RegisterCallback<T> (Action<T> callback);

这个足够好用了。

代码语言:javascript
复制
instance.RegisterCallback<string>(Callback); //method group
instance.RegisterCallback<string>(t => {}); //lambda 

现在,我想为这个接受async方法的方法创建一个重载。这样,我就可以在任务返回回调时使用它,并以不同的方式处理它们。

代码语言:javascript
复制
instance.RegisterCallback<string>(AsyncCallback); //method group with async

AsyncCallback在哪里

代码语言:javascript
复制
    private Task AsyncCallback(string s)
    {
        return Task.Delay(0);
    }

天真的方法是有一种像这样的方法:

代码语言:javascript
复制
void RegisterCallback<T>(Func<T, Type> callback);

不过,它也有一些问题:

代码语言:javascript
复制
//1
instance.RegisterCallback<string>(async t => await Task.Delay(0));
//2
instance.RegisterCallback<string>(AsyncCallback); //method group with async

第一个被解析为Action<T> callback重载,第二个由于不明确的调用而无法编译。

好吧,合乎道理和我对这个界面很满意:

代码语言:javascript
复制
 void RegisterAsyncCallback<T>(Func<T, Task> callback);   

但是,这两个调用的编译没有问题:

代码语言:javascript
复制
   instance.RegisterCallback<string>(async t => await Task.Delay(0));
   instance.RegisterAsyncCallback<string>(async t => await Task.Delay(0));

是否有一种方法来设计这个公共api,以便用户只对一个方法使用void回调,而对另一个方法返回任务。

也许有人能告诉我,在现有的api中,类似的问题已经解决了?

完整的代码可以找到这里

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-22 13:38:34

这里没有很好的解决方案;要么方法重载时会出现不明确的调用错误,要么就会有一个全新的API。

就我个人而言,我将添加Func<T, Task>重载并接受中断更改,不再允许方法重载。或者,您可以在新方法(RegisterCallbackEx?)上创建两个重载。并将旧代码标记为Obsolete --这将允许旧代码编译,但鼓励开发人员更改调用。

也许有人能告诉我,在现有的api中,类似的问题已经解决了?

好吧,我可以给你们举个例子,一个类似的问题没有解决。:)

Task.Factory.StartNew通常用于将工作排队到线程池。它是Action-based,我相信它适用于方法组。

当.NET团队想要添加异步支持时,他们引入了一个新的API:Task.Run,它是为ActionFunc<Task>重载的。

(请注意,在这种情况下,Task.Run在技术上只支持StartNew使用的一个子集,而StartNew没有标记为Obsolete)。

他们考虑了自己的选择,但这是他们能想到的最好的选择。请注意,仍然存在以下问题,因此,开发人员经常就这两个问题提出问题:

  • Task.Run不支持方法组。
  • StartNew将在async lambda中编译得很好,但会以令人惊讶的方式运行(由于async void)。

由于他们正在改变.NET BCL,所以向后兼容性是最重要的。对于个人库,我更喜欢更安全/更干净的API,而不是严格的向后兼容性,因此在您的情况下,我会做出另一个选择(即添加Func<T, Task>重载作为主要版本升级的一部分)。

票数 3
EN

Stack Overflow用户

发布于 2016-01-22 13:16:30

是否有一种方法来设计这个公共api,以便用户只对一个方法使用空回调,而对另一个方法返回任务。

不,不是真的。问题是Action<T>委托。它允许大量不同的lambda表达式,正如您已经发现的那样。您将在RegisterCallback(Action<T> callback)中遇到的一个主要问题--如果有人像这样使用它:

代码语言:javascript
复制
instance.RegisterCallback<string>(async _ => await Task.Delay(0));

他们正在创建一个async void,这是一个巨大的问题。你对Func<T, Task>有了正确的想法。另外,我喜欢您重命名函数并添加“异步”的想法,RegisterAsyncCallback(Func<string, Task> callback)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34947128

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档