【发布时间】:2018-07-13 11:19:31
【问题描述】:
我想要一堆 GetDataAsync() 方法,这些方法被重载以根据所需类型返回各种数据集。如果函数不是异步的,我可以根据out 参数重载:
public void GetData(int userId, out int age, out string name) { ... }
public void GetData(int userId, out string name, out string address) { ... }
但是out 不允许用于async 方法。接下来,我尝试使用泛型来重载(我将string 和int 更改为其他类型,因为这个技巧对密封类无效):
public async Task<Tuple<TName, TAddress>> GetDataAsync<TName, TAddress>(int userId)
where TAddress : Address where TName : Name
{ ... }
public async Task<Tuple<TAge, TName>> GetDataAsync<TAge, TName>(int userId)
where TAge : Age where TName : Name
{ ... }
但我认为模板专业化在 C# 中并不存在,因此这些被认为是相同的功能。
确实启用此重载的丑陋技巧是传入函数填充的缓冲区:
public async Task GetDataAsync(int userId, int[] id_output, string[] name_output)
{
await Task.Delay(10);
id_output[0] = 60;
name_output[0] = "Freddy";
}
public async Task GetDataAsync(int userId, string[] name_output, string[] address_output)
{
await Task.Delay(10);
name_output[0] = "Freddy";
address_output[0] = "Elm Street";
}
但是那个 hack 有一个糟糕的 API。 (使用列表作为缓冲区会更安全一些。)是否有任何适当的 C# 方法可以从异步重载中获取不同的数据类型?如果必须,我会将数据类型合并到函数名称中而不是重载,但这似乎是不必要的冗长。而且由于函数抽象了数据库调用,其中一些函数的名称确实很长! (这些函数大多有不止一个调用者,因此希望集中定义它们,而不是在调用它们的类中。)
【问题讨论】:
-
我不认为
GetData是一个很好的名字。不是每个提供某种形式的输出的方法都会获取数据吗?他们真的有如此密切的关系,以至于他们应该有相同的名字吗?在我看来,他们似乎没有。 -
@Damien_The_Unbeliever 每个方法从数据库中获取两条或更多条数据(单行的一部分),并初始化每条数据(通常是 JSON 的反序列化)。在我看来,这些方法大体相似。
-
@piojo - 但可能不适用于获得您的代码并被告知使用它的人。太笼统了。他们肯定有更具体的目的。
-
@Sinatr 一个函数不允许只通过返回类型来区分,否则这不会是一个问题。
-
在编译时选择重载对您来说有多重要?如果您有一个(公共)通用方法,然后在执行时填充正确的值,那是否足够好?如果您使用不受支持的组合,则不会出现编译时错误,但否则它会起作用。我会把它写成答案,但是写起来需要一段时间,如果编译时验证是必须的,我不想浪费时间。 (如果只有 您的 代码会调用它,并且都经过单元测试,那可能不是问题。)
标签: c# async-await overloading