返回多种类型

Lib*_*eph 2 c# function c#-4.0 xamarin

我的 xamarin 应用程序中有一个方法可以从服务器获取一些数据,如果 HTTP 请求成功,我需要该方法返回数据,或者如果服务器返回错误,则返回“系统错误”字符串,或者“Internet 连接” error" 字符串,如果没有连接。

我想知道如何设置返回类型以返回其中之一。我知道元组可以返回多个。但我相信两者兼而有之,而不是两者兼而有之。

我的代码

public async Task<List<AllReportVM>> GetAllReports(string token, string username)
    {
        var httpClient = GetHttpClient();
        if (CrossConnectivity.Current.IsConnected) {
            var response = await httpClient.GetAsync ("getdashboardreports.ashx").ConfigureAwait (false);

            if (response.IsSuccessStatusCode) {
                var content = response.Content;

                string jsonString = await content.ReadAsStringAsync ().ConfigureAwait (false);

                return JsonConvert.DeserializeObject<List<AllReportVM>> (jsonString);
            } else {
                return "SystemError";
            }
        } else {
            return "Internet Connectivity Error";

        }
    }
Run Code Online (Sandbox Code Playgroud)

p.s*_*w.g 5

你所要求的实际上是一个受歧视的工会。C# 本身并没有这样的东西。有几种方法可以解决这个问题。首先,考虑我所说的试用/试用模式:

public bool GetAllResults(string token, string username, out List<AllReportVM> results);
Run Code Online (Sandbox Code Playgroud)

这对于相对简单的方法来说是可以的,但它实际上并没有给您错误消息(至少考虑到它通常的实现方式)并且out参数不适用于async方法。所以我们可以排除这种情况。

第二种选择是对错误抛出异常,这是我在 90% 的情况下推荐的:

public async Task<List<AllReportVM>> GetAllReports(string token, string username)
{
    var httpClient = GetHttpClient();
    if (CrossConnectivity.Current.IsConnected) {
        var response = await httpClient.GetAsync ("getdashboardreports.ashx").ConfigureAwait (false);

        if (response.IsSuccessStatusCode) {
            var content = response.Content;

            string jsonString = await content.ReadAsStringAsync ().ConfigureAwait (false);

            return JsonConvert.DeserializeObject<List<AllReportVM>> (jsonString);
        } else {
            throw new RequestException("SystemError");
        }
    } else {
        throw new RequestException("Internet Connectivity Error");
    }
}
Run Code Online (Sandbox Code Playgroud)

要调用它,您必须使用:

try 
{
    var list = await obj.GetAllReports(token, username);
    ...
}
catch (RequestException ex)
{
    Console.WriteLine(ex.Message);
}
Run Code Online (Sandbox Code Playgroud)

这是一个非常可靠、完善的模式。事实上,您可能应该已经对可能在您的应用程序中发生的各种其他异常使用异常处理。但是,它确实有一些性能影响,您应该避免对简单控制流使用异常。对于需要发出大量请求并期望有效处理故障(例如批处理)的应用程序,这可能不是一个选项。当我过去遇到这样的情况时,我发现实现自定义类很有用,例如:

public class RequestResult<T>
{
    public bool Success { get; }
    public T Result { get; }
    public string ErrorMessage { get; }

    private RequestResult(bool success, T result, string errorMessage)
    {
        this.Success = success;
        this.Result = result;
        this.ErrorMessage = errorMessage;
    }

    public static RequestResult<T> Success(T result)
    {
        return new RequestResult<T>(true, result, null);
    }

    public static RequestResult<T> Failure(string errorMessage)
    {
        return new RequestResult<T>(false, default(T), errorMessage);
    }
}

public async Task<RequestResult<List<AllReportVM>>> GetAllReports(string token, string username)
{
    var httpClient = GetHttpClient();
    if (CrossConnectivity.Current.IsConnected) {
        var response = await httpClient.GetAsync ("getdashboardreports.ashx").ConfigureAwait (false);

        if (response.IsSuccessStatusCode) {
            var content = response.Content;

            string jsonString = await content.ReadAsStringAsync ().ConfigureAwait (false);

            var result = JsonConvert.DeserializeObject<List<AllReportVM>> (jsonString);
            return RequestResult.Success(result);
        } else {
            return RequestResult.Failure("SystemError");
        }
    } else {
        return RequestResult.Failure("Internet Connectivity Error");
    }
}
Run Code Online (Sandbox Code Playgroud)