简体   繁体   English

使用C#6进行一行方法调用以获得等待方法?

[英]One line method invocation with C# 6 for an awaitable method?

In Jon Skeet's C# 6 post entitled Clean Event Handlers Invocation with C# 6 he shows how you can now write 在Jon Skeet的C#6帖子中用C#6命名了Clean Event Handlers Invocation,他展示了你现在如何写作

public void OnFoo()
{
    Foo?.Invoke(this, EventArgs.Empty);
}

instead of 代替

public void OnFoo()
{
    EventHandler handler = Foo;
    if (handler != null)
    {
        handler(this, EventArgs.Empty);
    }   
}

Is there any way to do a one-liner like that if we're talking about an awaitable method? 如果我们谈论一个等待的方法,有没有办法做这样的单线程? If I try 如果我试试

await Foo?.Invoke();

I get the following compile error: 我得到以下编译错误:

The awaiter type System.Runtime.CompilerServices.TaskAwaiter? awaiter类型System.Runtime.CompilerServices.TaskAwaiter? must have suitable IsCompleted and GetResult members (CS4011). 必须有合适的IsCompletedGetResult成员(CS4011)。

Note: I am using Mono (Xamarin Studio for OSX v5.9.5), so the compiler results can vary from what one might get using Visual Studio. 注意:我使用的是Mono(Xamarin Studio for OSX v5.9.5),因此编译器结果可能与使用Visual Studio的结果不同。

@i3arnon Has a good solution, however this is another way that you could do it that wouldn't require adding a field or property. @ i3arnon有一个很好的解决方案,但这是你可以做到的另一种不需要添加字段或属性的方法。

await (Foo?.Invoke() ?? Task.CompletedTask);

or if Task<T> 或者如果Task<T>

var i = await (Foo?.Invoke() ?? Task.FromResult<T>(default(T)))

Not if you're trying to use the null propagation operator (ie ?. ). 如果您尝试使用空传播运算符(即?. ),则不会。

When you use this operator the result must be of a nullable type, since it may or may not invoke the method (depending on whether Foo is null ). 当您使用此运算符时,结果必须是可空类型,因为它可能会或可能不会调用该方法(取决于Foo是否为null )。 Reference types are nullable but value types (structs) are not so for them this operator returns Nullable<T> ( T? ). 引用类型是可空的但是值类型(结构)对于它们不是这样的,这个运算符返回Nullable<T>T? )。

When you await something it compiles into calling GetAwaiter on that awaitable (usually a Task ) and getting an awaiter (usually TaskAwaiter ) that has IsCompleted , GetResult and OnCompleted . await它时,它会编译为在等待(通常是Task )上调用GetAwaiter并获得具有IsCompletedGetResultOnCompleted的awaiter(通常是TaskAwaiter )。 If a type doesn't have all these then it's not awaitable and you can't await it. 如果某种类型没有所有这些,则它不是等待的,你不能等待它。

So in your case, you call Foo?.Invoke() and get back a Nullable<TaskAwaiter> (ie TaskAwaiter? ) since TaskAwaiter is a struct and TaskAwaiter? 那么在你的情况下,你调用Foo?.Invoke()并返回一个Nullable<TaskAwaiter> (即TaskAwaiter? ),因为TaskAwaiter是一个结构和TaskAwaiter? doesn't have the required methods (unlike TaskAwaiter itself) it can't be awaited (it wouldn't have been possible even if TaskAwaiter was a class since you can't await a null ). 没有所需的方法(与TaskAwaiter本身不同)它是无法等待的(即使TaskAwaiter是一个类也不可能,因为你不能等待null )。

However, you can simply initialize Foo with an efficient dummy registration so it wouldn't ever be null and you wouldn't need to check it: 但是,您可以使用有效的虚拟注册简单地初始化Foo ,因此它不会为null ,您不需要检查它:

Func<Task> Foo = () => Task.CompletedTask;

public void OnFoo()
{
    await Foo();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM