首页 > 解决方案 > 如何使用 C# 异步方法重载和返回多种类型?

问题描述

我想要一堆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方法。接下来,我尝试使用泛型来重载(我更改了stringint其他类型,因为这个技巧对密封类无效):

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# 中并不真正存在,因此这些被认为是相同的功能。

启用此重载的丑陋 hack 是传入函数填充的缓冲区:

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# 方法可以从异步重载中获取不同的数据类型?如果必须,我会将数据类型合并到函数名称中而不是重载,但这似乎是不必要的冗长。而且由于函数抽象了数据库调用,其中一些函数的名称确实很长!(这些函数大多有不止一个调用者,因此希望集中定义它们,而不是在调用它们的类中。)

标签: c#async-awaitoverloading

解决方案


out创建参数是为了返回多个值,但它们不适用于异步方法,因为实际方法在概念方法结束执行之前返回。

这就是为什么将元组添加到语言中的原因。

元组表示一组松散相关的值。它们并非旨在表示数据库原始、实体或任何具有其自身含义/概念的事物。

数组也不是一个好的选择,因为您不能保证将数组作为方法参数一无所获,并且出于此目的,它们根本不是强类型的。

您似乎正在寻找的是泛型

Task<Response> GetAsync<Request, Response>(TRequest request);

推荐阅读