用于返回Task的异步方法的ConditionalAttribute的等效方式

3

我想编写一个async方法,但我希望只有在特定的编译常数被编译时才能调用它。

一种方法

一种方法是使用pragma指令,也就是条件编译常数,如下所示:

// 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;  

}

虽然我可以让我的异步方法返回 void 而不是 Task,但我对这样做感到非常不舒服。

那么,是否有一个类似于 ConditionalAttribute 的东西可用于想要返回值的方法?或者至少对于那些只想返回一个 Task 的方法是否有一个?


你可以自己制作程序集属性并动态构建它,但我不确定这是否符合您的要求?您能告诉我们,您如何传递这个常量“FOO”,您是想通过常量还是动态创建来实现,并且您计划如何更改它? - kuskmen
1个回答

1
如果您使用您的条件编译,您希望发生什么?它应该返回null吗?还是已完成任务?或者失败的任务?
可能的解决方案是像这样编写您的异步方法:
#if FOO
public Task DoFooAsync() => Task.FromResult(0);
#else 
public Task DoFooAsync()
{
    //...
}
#endif

如果您使用条件符号编译程序集,那么您的调用者将会得到一个空任务。

在 .Net Framework 4.6+ 中,您可以使用 Task.CompletedTask 替代 Task.FromResult(0) - svick
@svick 你说得对。但是这个答案与我所问的问题无关。他们可能匆忙阅读了问题。 - Water Cooler v2
我想预期的效果是在编译时忽略方法定义和调用。它不需要“返回”任何东西。 - Sinaesthetic
更正一下,显然这比不编译它要复杂一些。由Eric Lippert解释:https://dev59.com/g6Dia4cB1Zd3GeqPC2IP - Sinaesthetic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接