如何重构此代码以不返回null两次?

时间:2014-01-17 18:11:45

标签: c# exception null json.net conditional-statements

我有这个代码,如果在异常的情况下遇到错误的结果,则返回null:

private JArray GetRESTData(string uri)
{
    try
    {
        var webRequest = (HttpWebRequest)WebRequest.Create(uri);
        var webResponse = (HttpWebResponse)webRequest.GetResponse();
        if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0))
        {
            var reader = new StreamReader(webResponse.GetResponseStream());
            string s = reader.ReadToEnd();
            return JsonConvert.DeserializeObject<JArray>(s);
        }
        MessageBox.Show(string.Format("Status code == {0}", webResponse.StatusCode));
        return null;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return null;
    }
}

......但闻起来有点腐臭。有没有办法可以重构这个,不要两次调用“return null”?

3 个答案:

答案 0 :(得分:4)

我建议您不要在此函数中处理异常,假设它的行为正确。

private JArray GetRESTData(string uri)
{
    var webRequest = (HttpWebRequest)WebRequest.Create(uri);
    var webResponse = (HttpWebResponse)webRequest.GetResponse();

    var reader = new StreamReader(webResponse.GetResponseStream());
    string s = reader.ReadToEnd();

    return JsonConvert.DeserializeObject<JArray>(s);
}

我删除了StatusCode检查,因为如果HttpWebResponse类不是有效的状态代码,它就会抛出异常。

此方法的责任应该是获取其余数据,而不是处理用户交互(MessageBox)。

为了进一步重构,我会创建另一个方法来发出web请求,另一个方法来解析响应。

private JArray GetRESTData(string uri)
{
    var json = ReadFromUri(uri);

    return JsonConvert.DeserializeObject<JArray>(json);
}

private string ReadFromUri(string uri)
{
    using (var webRequest = (HttpWebRequest)WebRequest.Create(uri))
    using (var webResponse = (HttpWebResponse)webRequest.GetResponse())
    using (var reader = new StreamReader(webResponse.GetResponseStream()))
    {
        return reader.ReadToEnd();
    }   
}

使用此方法:

try 
{
    var myArray = GetRESTData("http://someservice.com/bananabread");
} 
catch (WebException exception)
{
    MessageBox.Show("Some exception happened: {0}", exception);
}

答案 1 :(得分:2)

只需将退货移出try / catch块

try
{
    var webRequest = (HttpWebRequest)WebRequest.Create(uri);
    var webResponse = (HttpWebResponse)webRequest.GetResponse();
    if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0))
    {
        var reader = new StreamReader(webResponse.GetResponseStream());
        string s = reader.ReadToEnd();
        return JsonConvert.DeserializeObject<JArray>(s);
    }
    MessageBox.Show(string.Format("Status code == {0}", webResponse.StatusCode));    
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);

}
return null;

答案 2 :(得分:2)

我更喜欢单个返回点,如果可能

private JArray GetRESTData(string uri)
{
    JArray ret = null; // single return value, declared outside of try/catch
    try
    {
        var webRequest = (HttpWebRequest)WebRequest.Create(uri);
        var webResponse = (HttpWebResponse)webRequest.GetResponse();
        if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0))
        {
            var reader = new StreamReader(webResponse.GetResponseStream());
            string s = reader.ReadToEnd();
            ret = JsonConvert.DeserializeObject<JArray>(s);
        }
        MessageBox.Show(string.Format("Status code == {0}", webResponse.StatusCode));
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    return ret;
}

注意:在这个简单的例子中,这可能已经足够了。在更复杂的函数中,如果已构造但处于无效状态,您可能希望在异常处理程序中将ret设置为null。但是,如果您正在使用RAII,那么这不应该是一个问题。