无法将表达式类型null转换为返回类型T.

时间:2014-01-30 03:01:21

标签: c# generics async-await asp.net-mvc-5.1

如何获取下面的HttpGet函数来填充所有响应(用#2表示)?我似乎无法声明一个适当类型的集合来处理添加每个响应。到目前为止我尝试的所有内容都给出了编译器错误:

  

'无法将表达式类型null转换为返回类型T`。

C#/ ASP.NET / MVC 5.1 / .NET 4.5

public async Task<IList<T>> Query<T>(string query)
{
    var response = await _serviceHttpClient.HttpGet<IList<T>>(string.Format("query?q={0}", query), "records");
    return response;
}

public async Task<T> HttpGet<T>(string urlSuffix, string nodeName)
{
    // #1 var list = ???
    var r = new QueryResult<T>();
    do
    {
        r = await HttpGetInternal<T>(urlSuffix, nodeName);

        // #2 list = r.Records
    } while (!string.IsNullOrEmpty(r.NextRecordsUrl));

    return // #3 list;
}

private async Task<QueryResult<T>> HttpGetInternal<T>(string urlSuffix, string nodeName)
{
    var url = Common.FormatUrl(urlSuffix, _instanceUrl, _apiVersion);

    var request = new HttpRequestMessage()
    {
        RequestUri = new Uri(url),
        Method = HttpMethod.Get
    };

    request.Headers.Add("Authorization", "Bearer " + _accessToken);

    var responseMessage = await _httpClient.SendAsync(request);
    var response = await responseMessage.Content.ReadAsStringAsync();

    if (responseMessage.IsSuccessStatusCode)
    {
        var jObject = JObject.Parse(response);
        var jToken = jObject.GetValue(nodeName);
        var res = JsonConvert.DeserializeObject<T>(jToken.ToString());

        var r = new QueryResult<T>()
        {
            NextRecordsUrl = jObject.GetValue("nextRecordsUrl").ToString(),
            Records = res
        };

        return r;
    }

    var errorResponse = JsonConvert.DeserializeObject<ErrorResponses>(response);
    throw new ForceException(errorResponse[0].errorCode, errorResponse[0].message);
} 

public class QueryResult<T>
{
    public int TotalSize { get; set; }
    public bool Done { get; set; }
    public string NextRecordsUrl { get; set; }
    public T Records { get; set; }
}

1 个答案:

答案 0 :(得分:0)

我会更改签名以返回IList<T>与调用它的方法相同,因为没有一种简单的方法来创建实现泛型指定的接口的东西。另一个替代方法是使用具体类型调用它,比如说List<T>,它实现了调用者的返回接口,但我认为另一种方式更清晰。

由于r.Records类型为T,因此应该可以将其添加到List<T>List<T>实现IList<T>,从而满足返回类型。

public async Task<IList<T>> Query<T>(string query)
{
    var response = await _serviceHttpClient.HttpGet<T>(string.Format("query?q={0}", query), "records");
    return response;
}

public async Task<IList<T>> HttpGet<T>(string urlSuffix, string nodeName)
{
    var list = new List<T>();

    do
    {
        var r = await HttpGetInternal<T>(urlSuffix, nodeName);

        list.Add(r.Records);
    }
    while (!string.IsNullOrEmpty(r.NextRecordsUrl));

    return list;
}