2015-08-18 78 views
3

在題爲Clean Event Handlers Invocation with C# 6喬恩斯基特的C#6後,他展示瞭如何寫信對於等待方法,用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(); 

我得到以下編譯錯誤:

The awaiter type System.Runtime.CompilerServices.TaskAwaiter? must have suitable IsCompleted and GetResult members (CS4011).

注:我使用單聲道(Xamarin Studio中OSX v5.9.5),因此編譯器的結果可能是人們可能會發生變化使用Visual Studio。

+0

無關,你應該在.NET的東西的Windows VM代碼。在OSX上有更好的體驗。對不起主題。我不認爲你可以等待,因爲它沒有報告狀態方法。 – Botonomous

+0

我都這樣做,我發現在OSX上工作要比在虛擬機上工作要好得多(即使有關鍵重新映射等)。還是)感謝你的建議! –

+1

我試圖在Visual Studio中重現這一點,並沒有得到編譯器錯誤,但我得到了一個關於可能的null異常的警告。 – HaroldHues

回答

5

@ i3arnon具有良好的解決方案,但是這是另一種方式,你可以做到這一點,不需要添加一個字段或屬性。

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

,或者如果Task<T>

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

真棒解決方法! –

+0

什麼命名空間或.NET版本是'Task.CompletedTask'中的?我沒有那個財產/領域。 – valdetero

+0

@valdetero .NET 4.6。截至今天,Mono不幸在Mono上無法使用。 Task.FromResult雖然工作。 –

4

若你想使用空傳播經營者(即?.)。

當使用此操作的結果必須是空類型的,因爲它可以或可以不調用方法(取決於Foo是否是null)。參考類型可爲空,但值類型(結構)不適合它們。此運算符返回Nullable<T>T?)。

當你await東西它編譯成上awaitable(通常爲Task)調用GetAwaiter,卻得到了awaiter(通常TaskAwaiter),有IsCompletedGetResultOnCompleted。如果一個類型沒有所有這些,那麼它不是等待的,你不能等待它。

所以你的情況,你叫Foo?.Invoke()並取回一個Nullable<TaskAwaiter>(即TaskAwaiter?),因爲TaskAwaiter是一個結構和TaskAwaiter?不具備所需的方法(不像TaskAwaiter本身)不能等待(它止跌」即使TaskAwaiter是一類,因爲你不能等待null)。

但是,你可以簡單地用一個高效的虛擬註冊初始化Foo所以它不會永遠是null,你不會需要檢查它:

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

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

爲什麼_why_問題的優秀解釋不能編譯。 –

+0

什麼命名空間或.NET版本是'Task.CompletedTask'中的?我沒有那個財產/領域。 – valdetero

+0

@valdetero它在.Net 4.6上。 – i3arnon