在方法名称中使用“asynchronous”后缀取决于是否使用“asynchronous”修饰符?

什么是“Async”的后缀方法名称的约定?

应该将“Async”后缀仅附加到使用async修饰符声明的方法吗?

 public async Task<bool> ConnectAsync() 

或者只是返回Task<T>Task

 public Task<bool> ConnectAsync() 

我认为,即使从微软的文档来看,事实也是模棱两可的:

在Visual Studio 2012和.NET Framework 4.5中,使用async关键字(Visual Basic中的asynchronous)归因的任何方法都被视为asynchronous方法,并且C#和Visual Basic编译器将执行必要的转换以通过使用asynchronous实现方法TAP。 一个asynchronous方法应该返回一个Task或一个Task<TResult>对象。

http://msdn.microsoft.com/en-us/library/hh873177(v=vs.110).aspx

这不正确。 任何使用async方法都是asynchronous的,然后它说它应该返回一个Task或者Task<T> – 这不适用于调用堆栈顶部的方法,例如Button_Click或者async void

当然,你必须考虑公约的重点是什么?

您可以说Async后缀约定是与API用户通信,该方法是可以等待的。 对于需要等待的方法来说,它必须返回Task作为void,或者Task<T>作为返回值的方法,这意味着只有后者可以用Async作为后缀。

或者你可能会说Async后缀约定是传递方法可以立即返回,放弃当前线程执行其他工作,并可能导致竞争。

这个Microsoft doc报价说:

按照惯例,您将“Async”附加到具有Async或Async修饰符的方法的名称。

http://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_NamingConvention

这甚至没有提到你自己的asynchronous方法返回Task需要Async后缀,我认为我们都同意他们这样做。


所以这个问题的答案可能是:两者。 在这两种情况下,都需要使用async关键字将Async附加到方法,并返回TaskTask<T>


我要请斯蒂芬·图布(Stephen Toub)澄清这个情况。

更新

所以我做了。 这就是我们的好人写的:

如果公共方法是返回任务并且本质上是asynchronous的(与已知的方法相比,总是同步完成但仍然返回任务的原因),它应该有一个“Async”后缀。 这是指导原则。 这里命名的主要目标是使消费者非常明显地意识到被调用的方法可能不会同步完成所有的工作; 它当然也有助于在同步和asynchronous方法中暴露function的情况,这样您需要名称区别来区分它们。 该方法如何实现其asynchronous实现对于命名无关紧要:是使用async / await来获得编译器的帮助,还是直接使用System.Threading.Tasks的types和方法(如TaskCompletionSource)并不重要,因为就方法的消费者而言,这不影响方法的签名。

当然,指南总是有例外的。 在命名的情况下,最值得注意的是,整个types的存在理由是提供asynchronous聚焦的function,在这种情况下,每种方法的asynchronous都是过度的,例如任务本身产生其他任务的方法。

对于无返回asynchronous方法,不希望有公共表面区域的方法,因为调用者无法知道asynchronous工作何时完成。 但是,如果您必须公开公开无返回asynchronous方法,那么您可能希望拥有一个表示正在启动asynchronous工作的名称,如果有意义,则可以在此处使用“Async”后缀。 鉴于这种情况应该是罕见的,我认为这确实是一个个案的决定。

我希望Steve帮助

斯蒂芬的开头句子简洁明了, 它排除了async void因为想用这样的devise创build一个公共API是不正常的,因为实现asynchronous无效的正确方法是返回一个纯粹的Task实例,并让编译器达到它的魔力。 但是,如果您确实需要public async void ,则build议添加Async 。 其他顶级的async void方法,如事件处理程序通常不公开,并不重要/限定。

对我来说,它告诉我,如果我发现自己想知道async void后缀Async ,我应该把它变成一个async Task以便调用者可以等待它,然后追加Async

什么是“Async”后缀方法名称的约定。

基于任务的asynchronous模式(TAP)规定,方法应该总是返回一个Task<T> (或Task ),并用Async后缀命名; 这与使用async是分开的。 Task<bool> Connect()async Task<bool> Connect()都会编译并运行,但是您不会遵循TAP命名约定。

该方法是否应该包含async修饰符,还是仅仅返回Task?

如果方法的主体(不pipe返回types或名称)包括await ,则必须使用async ; 编译器会告诉你:''await'操作符只能在一个asynchronous方法中使用……“。 返回Task<T>Task不“足够”,以避免使用async 。 有关详细信息,请参阅asynchronous(C#参考) 。

即这些签名是正确的:

async Task<bool> ConnectAsync()Task<bool> ConnectAsync()正确地遵循TAP约定。 你总是可以使用async关键字,但是你会得到一个编译器警告:“这个asynchronous方法缺less'等待'操作符,并且会同步运行……”如果主体不使用await

或者它只是返回任务?

那。 async关键字在这里不是真正的问题。 如果在不使用async关键字的情况下实现asynchronous,则在一般意义上,该方法仍然是“Async”。

由于TaskTask<T>都是等待types,它们表示一些asynchronous操作。 或者至less他们应该代表。

你应该为一个方法添加后缀Async ,在某些情况下(不一定全是)不会返回一个值,而是返回一个正在进行的操作的包装。 该包装通常是一个Task ,但在Windows RT上它可以是IAsyncInfo 。 遵循你的直觉,记住,如果你的代码的用户看到Async函数,他或她会知道该方法的调用与该方法的结果分离,并且他们需要采取相应的行动。

请注意,有些方法如Task.DelayTask.WhenAll返回Task ,但没有Async后缀。

另外请注意,有async void方法代表火灾,忘记asynchronous方法,你应该更好地意识到,方法是build立在这样的方式。

在使用asynchronous和等待(C#)的asynchronous编程中 ,Microsoft提供了以下指导:

命名约定

按照惯例,您将“Async”附加到具有asynchronous修饰符的方法的名称中。

您可以忽略事件,基类或接口合约表示不同名称的约定。 例如,您不应该重命名通用事件处理程序,如Button1_Click

我觉得这个指导不完整和不令人满意。 这是否意味着在没有async修饰符的情况下,这个方法应该被命名为Connect而不是ConnectAsync

 public Task<bool> ConnectAsync() { return ConnectAsyncInternal(); } 

我不这么认为。 正如@Servy 简洁的答案和@Luke Puplett提供的更详细的答案所表明的 ,我认为这个方法应该被命名为ConnectAsync (因为它返回一个等待状态)是合适的。 在进一步的支持, @John Skeet在这个答案的另一个问题追加Async的方法名称,无论async修饰符的存在。

最后,在另一个问题上 ,请考虑@Damien_The_Unbeliever的 评论 :

async/await是你方法的实现细节。 关于您的方法是否被声明为async Task Method()或者只是Task Method() ,关于您的调用者而言,不重要。 (事实上​​,你可以随时在这两者之间进行切换,而不会被视为一个突破性的改变。)

从那里,我推断这是方法的asynchronous性质 ,决定了它应该如何命名。 该方法的用户甚至不知道在其实现中是否使用了async修饰符(没有C#源代码或CIL)。

我认为如果它返回一个Task,它应该使用Async-suffix,而不pipe这个方法是用async修饰符声明的。

其原因是在界面中声明了该名称。 接口声明返回types是一个Task 。 那么这个接口有两个实现,一个实现使用async修饰符实现,另一个不实现。

 public interface IFoo { Task FooAsync(); } public class FooA : IFoo { public Task FooAsync() { /* ... */ } } public class FooB : IFoo { public async Task FooAsync() { /* ... */ } }