2017-05-15 51 views
1

我想編寫一個async方法,但我希望只有在使用特定編譯常量編譯程序集時才能調用它。等效於任務返回異步方法的ConditionalAttribute

ONE我能做到這一點WAY

一種方法是使用編譯指令,即條件編譯常量像這樣:

// Callee 
#if FOO 
    public async Task DoFooAsync() 
    { 
    ... 
    } 
#end if 

// Caller 1 
#if Foo 
    // fire and forget 
    DoFooAsync(); 
#endif 

// Caller 2 
#if Foo 
    public async Task<T> DoWork<T>() 
    { 
    T returnValue = default(T); 

    // fire but don't forget 
    var fooTask = DoFooAsync(); 

    // Prepare return value 
    returnValue = ...; 

    // Not terribly important but what if the caller wants 
    // to find out 
    if (fooTask.Status == Faulted) 
    { 
     // do something about it 
    } 
    } 
#endif 

正如你所看到的,它變得相當混亂的寫作所有這些。

另一種方式

這樣做將是使用ConditionalAttribute的其他方式。但是,從閱讀文檔看來,該屬性僅適用於返回void的方法。

尚未有這一制約因素,我會很容易使用的屬性一樣了,那會作出代碼,以便更加整潔,更加好來看待和解讀:

// Callee 
[Conditional("FOO")] 
public Task DoFooAsync() { ... } 

// Caller 
public async Task<T> DoWork<T>() 
{ 
    // fire and forget 
    DoFooAsync(); 

    // fire but would like to know what happened 
    var fooTask = DoFooAsync(); 

    T t = GetTee(); 

    if (fooTask.IsFaulted) { ... } 

    return t; 

} 

即使我有我的async方法返回void而不是Task,我覺得這樣做很不舒服。

那麼,對於想要返回值的方法,有沒有等效的ConditionalAttribute?至少對於那些想要返回Task的方法是否有一個?

+0

您可以創建自己的程序集屬性並動態構造它,但我不確定這是否是您想要的?你能告訴我們,你如何通過這個常量「FOO」,你想通過不斷或動態創建,然後你打算如何改變它? – kuskmen

回答

2

如果您在條件下編譯它,您會發生什麼?它應該返回null嗎?還是完成任務?或失敗的任務?

可能的解決辦法是寫你的異步方法是這樣的:

#if FOO 
public Task DoFooAsync() => Task.FromResult(0); 
#else 
public Task DoFooAsync() 
{ 
    //... 
} 
#endif 

,以便呼叫方將獲得空任務的情況下,你編譯你的條件符號的組合。

+0

在.Net Framework 4.6+上,您可以使用'Task.CompletedTask'而不是'Task.FromResult(0)'。 – svick

+0

@svick你說得對。但這個答案與我所問的問題無關。他們可能匆忙地閱讀這個問題。 –

+0

我想象的預期效果是在編譯時忽略方法定義和對它的調用。它不需要「返回」任何東西。 – Sinaesthetic