Jon Skeet的C#6帖子题为Clean Event Handlers Invocation with C# 6,他展示了你现在的写作方式
public void OnFoo()
{
Foo?.Invoke(this, EventArgs.Empty);
}
而不是
public void OnFoo()
{
EventHandler handler = Foo;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
如果我们谈论一个等待的方法,有没有办法像这样做一个单行?如果我试试
await Foo?.Invoke();
我收到以下编译错误:
awaiter类型
System.Runtime.CompilerServices.TaskAwaiter?
必须有合适的IsCompleted
和GetResult
成员(CS4011)。
注意:我使用的是Mono(Xamarin Studio for OSX v5.9.5),因此编译器结果可能与使用Visual Studio时的结果不同。
答案 0 :(得分:5)
@ i3arnon有一个很好的解决方案,但这是可以做的另一种方式,不需要添加字段或属性。
await (Foo?.Invoke() ?? Task.CompletedTask);
或Task<T>
var i = await (Foo?.Invoke() ?? Task.FromResult<T>(default(T)))
答案 1 :(得分:4)
如果您尝试使用空传播运算符(即?.
),则不会。
当您使用此运算符时,结果必须是可空类型,因为它可能会也可能不会调用该方法(取决于Foo
是否为null
)。引用类型可以为空,但值类型(结构)对于它们不是这样的,此运算符返回Nullable<T>
(T?
)。
当你await
某件事情汇编成在等待的GetAwaiter
上(通常是Task
)并获得TaskAwaiter
的等待者IsCompleted
},GetResult
和OnCompleted
。如果某种类型并不具备所有这些类型,那么它就不值得等待而且您无法等待它。
因此,在您的情况下,您致电Foo?.Invoke()
并取回Nullable<TaskAwaiter>
(即TaskAwaiter?
),因为TaskAwaiter
是一个结构而TaskAwaiter?
没有&#39} ; t具有所需的方法(与TaskAwaiter
本身不同)可以等待它(即使TaskAwaiter
是一个类,它也不可能,因为你不能等待null
)。
但是,您只需使用有效的虚拟注册来初始化Foo
,这样它就不会null
,您也不需要检查它:
Func<Task> Foo = () => Task.CompletedTask;
public void OnFoo()
{
await Foo();
}