什么是与“异步”后面添加方法名的约定?
应在“异步”后缀只附属于声明与方法async
修改?
public async Task<bool> ConnectAsync()
抑或是足够,该方法只返回Task<T>
或Task
?
public Task<bool> ConnectAsync()
什么是与“异步”后面添加方法名的约定?
应在“异步”后缀只附属于声明与方法async
修改?
public async Task<bool> ConnectAsync()
抑或是足够,该方法只返回Task<T>
或Task
?
public Task<bool> ConnectAsync()
我认为事实是不明确的,甚至从微软的文档:
在Visual Studio 2012和.NET Framework 4.5,即归因与任何方法
async
关键字(Async
在Visual Basic)被认为是一种异步方法,和C#和Visual Basic的编译器执行必要的转换,通过使用异步实现该方法TAP。 异步方法应当返回一个Task
或Task<TResult>
对象。
http://msdn.microsoft.com/en-us/library/hh873177(v=vs.110).aspx
这是不对的了。 用任何方法async
是异步的,那么它的说它应该返回一个Task
或Task<T>
-这是不正确的,在调用堆栈的顶部,Button_Click例如,或方法async void
。
当然,你要考虑的是该公约的意义呢?
你可以说, Async
后缀约定是沟通,该方法是awaitable的API用户。 一种方法是awaitable,它必须返回Task
为空隙,或Task<T>
为一个返回值的方法,这意味着只有后者可与后缀Async
。
或者你可能会说Async
后缀约定是沟通,该方法可以立即返回,放弃当前线程执行其他工作,并有可能导致种族。
这个微软DOC报价说:
按照惯例,您追加“异步”,以有一个异步或异步修饰符的方法的名称。
http://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_NamingConvention
其中甚至没有提到自己的异步方法返回Task
所需要的Async
后缀,这个我想大家都同意他们这样做。
所以,这个问题的答案可能是:两者。 在这两种情况下,你需要追加Async
与方法async
关键字和返回Task
或Task<T>
我要问斯蒂芬Toub澄清情况。
更新
所以我做了。 这里就是我们的好男人写道:
如果一个公共方法是任务的返回,并在本质上是异步的(而不是一个已知总是同步执行完毕的方法,但仍然会返回一个任务由于某种原因),它应该有一个“异步”后缀。 这就是指导方针。 与命名这里的主要目的是使它非常明显的是被调用将很有可能无法完成所有的同步工作的方法功能的消费者; 这当然也有助于在那里的功能进行曝光同步和异步方法,例如,你需要一个名字差别来区分它们的情况。 该方法是如何实现它的异步执行是无关紧要的命名:异步/等待是否用于争取编译器的帮助下,还是从System.Threading.Tasks类型和方法是直接使用(例如TaskCompletionSource)其实并不重要,因为不影响该方法的签名,只要方法的消费者来讲。
当然,总有一些例外的准则。 最显着的一个命名的情况是当整个类型存在的理由是提供异步聚焦功能的情况下,在这种情况下,每个方法具有异步会矫枉过正,例如在工作本身产生的其他任务的方法。
至于空隙返回异步方法,它不希望有那些在公共面积,因为调用者有当异步工作已经完成知道的没有什么好办法。 如果必须公开揭露空隙返回异步方法,不过,你可能不希望有传达异步工作正在启动的名称,如果它是有道理的,你可以在这里使用的“异步”后缀。 鉴于这种情况下应该怎么罕见的是,我要说这真是一个案件逐案样的决策。
我希望帮助,史蒂夫
从斯蒂芬的开幕式上一句简洁的指导是清楚。 它不包括async void
,因为它是不寻常的要创建一个公共API以来,以实现异步空的正确方法是这样的设计是返回一个简单的Task
实例,让编译器到它的魔力。 但是,如果你真的想要一个public async void
,则追加Async
建议。 其他顶级的堆栈async void
的方法,如事件处理程序通常不公开,不事/资格。
对我来说,它告诉我,如果我发现自己想知道后面添加Async
上的async void
,我也许应该把它变成一个async Task
,使呼叫者可以等待它,然后追加Async
。
我建了很多API,服务和其他调用系统中的大多数我的代码运行的异步的其他应用程序。
我自己的经验,我下面的规则是:
如果有返回相同的事情都非异步和异步方法我后缀异步一个带有Async。 否则不是。
例子:
只有一个方法:
public async Task<User> GetUser() { [...] }
同样的方法有两个特征:
public User GetUser() { [...] }
public async Task<User> GetUserAsync() { [...] }
这是有道理的,因为它是返回相同的数据,但唯一不同的事情就是返回数据 ,而不是数据本身的方式 。
我也觉得这个命名约定存在由于需要引入异步方法,并仍然保持向后兼容性。
我认为,新的代码不应该使用异步后缀。 这只是那样明显的返回类型为String,或者为智力在这个线程前面提到的。
什么是与“异步”后面添加方法名的约定。
的基于任务的异步模式(TAP)决定了方法应该总是返回一个Task<T>
或Task
),并用一个异步后缀命名; 这是从使用单独的async
。 这两个Task<bool> Connect()
和async
Task<bool> Connect()
将编译和运行得很好,但你不会是TAP命名约定以下。
如果该法包含的
async
修改,或者不够,它只是返回的任务?
如果该方法的主体(无论返回类型或名称)包含await
,您必须使用async
; 编译器会告诉你“在‘等待’运算符只能异步方法中使用。......”。 返回Task<T>
或Task
是不“足够”,以避免使用async
。 见异步(C#参考)了解详情。
即这些签名是正确的:
两个async
Task<bool> ConnectAsync()
和Task<bool> ConnectAsync()
适当地跟随TAP约定。 你总是可以使用async
的关键字,但你会得到一个编译器警告“这种异步方法缺乏‘等待’运营商和将同步运行。......”如果身体不使用await
。
或者它不够,它只是返回的任务?
那。 该async
关键字是不是在这里真正的问题。 如果要实现异步不使用async
关键字的方法仍然是“异步”,一般意义上的。
由于Task
和Task<T>
均为awaitable类型,它们表示一些异步操作。 或者至少他们应该代表。
你应该加后缀Async
到,在某些情况下(不一定是所有),不返回值的方法,而是返回围绕正在进行的操作的包装。 这包装通常是一个Task
,但在Windows RT也可以是IAsyncInfo
。 按照你的直觉,并记住,如果你的代码的用户看到的Async
函数,他或她就知道该方法的调用是从方法的结果分离,他们需要采取相应的行动。
请注意,有方法,如Task.Delay
和Task.WhenAll
其返回Task
,但不具备Async
后缀。
还要注意的是有async void
代表火,忘记异步方法的方法和你最好知道,方法是建立在这样的方式。
在异步编程与异步和等待(C#) ,微软提供了以下指导意见:
命名约定
按照惯例,您追加“异步”,以具有异步修饰符的方法的名称。
您可以忽略其中一个事件,基类或接口的合同表明不同的名称约定。 例如,你不应该重命名常见的事件处理程序,如
Button1_Click
。
我觉得这是不完整的指导和未能如愿。 这是否意味着,在没有的async
调节剂,这种方法应该命名为Connect
,而不是ConnectAsync
?
public Task<bool> ConnectAsync()
{
return ConnectAsyncInternal();
}
我不认为如此。 正如指出的回答言简意赅由@Servy和更详细的解答由@Luke Puplett ,我认为这是适当的,确实预计这一方法应该被命名为ConnectAsync
(因为它返回一个awaitable)。 为了进一步支持这一点, @约翰飞碟双向在此回答另一个问题时追加Async
不管存在的方法名async
修改。
最后,在另一个问题 ,认为此评论的@Damien_The_Unbeliever :
async/await
是你的方法实现细节。 重要的不是一个小额你的方法是否声明async Task Method()
,或只是Task Method()
,只要您来电者的关注。 (事实上,你可以自由在没有它被认为是一个重大更改以后的某个时间在这两者之间变化。)
从这一点,我推断,这是决定它应该如何被命名为方法的异步特性 。 该方法的用户甚至不知道是否在async
在其实施改性剂(不含C#源代码或CIL)。
我认为,如果如果该方法与声明,无论返回一个任务就应该使用异步后缀async
修改与否。
其背后是该名称在接口中声明的原因。 接口声明的返回类型是一个Task
。 然后,有接口的两个实现,一个实现实现使用它async
修改,其他没有。
public interface IFoo
{
Task FooAsync();
}
public class FooA : IFoo
{
public Task FooAsync() { /* ... */ }
}
public class FooB : IFoo
{
public async Task FooAsync() { /* ... */ }
}