Я пытаюсь стать лучше в обработке исключений, но я чувствую, что мой код становится очень уродливым, нечитаемым и загроможденным, когда я стараюсь изо всех сил ловить их.Мне бы очень хотелось увидеть, как другие люди подходят к этому, приводя практический пример и сравнивая решения.
Мой метод примера загружает данные из URL-адреса и пытается сериализовать их в заданный тип, а затем возвращает экземпляр, заполненныйdata.
Во-первых, без какой-либо обработки исключений:
private static T LoadAndSerialize<T>(string url)
{
var uri = new Uri(url);
var request = WebRequest.Create(uri);
var response = request.GetResponse();
var stream = response.GetResponseStream();
var result = Activator.CreateInstance<T>();
var serializer = new DataContractJsonSerializer(result.GetType());
return (T)serializer.ReadObject(stream);
}
Мне кажется, что этот метод достаточно читабелен, как этот.Я знаю, что в методе есть несколько ненужных шагов (например, WebRequest.Create () может принимать строку, и я мог бы цеплять методы, не задавая их переменные), но я оставлю это так, чтобы лучше сравнивать с версией с исключением -обработка.
Это первая попытка обработать все, что может пойти не так:
private static T LoadAndSerialize<T>(string url)
{
Uri uri;
WebRequest request;
WebResponse response;
Stream stream;
T instance;
DataContractJsonSerializer serializer;
try
{
uri = new Uri(url);
}
catch (Exception e)
{
throw new Exception("LoadAndSerialize : Parameter 'url' is malformed or missing.", e);
}
try
{
request = WebRequest.Create(uri);
}
catch (Exception e)
{
throw new Exception("LoadAndSerialize : Unable to create WebRequest.", e);
}
try
{
response = request.GetResponse();
}
catch (Exception e)
{
throw new Exception(string.Format("LoadAndSerialize : Error while getting response from host '{0}'.", uri.Host), e);
}
if (response == null) throw new Exception(string.Format("LoadAndSerialize : No response from host '{0}'.", uri.Host));
try
{
stream = response.GetResponseStream();
}
catch (Exception e)
{
throw new Exception("LoadAndSerialize : Unable to get stream from response.", e);
}
if (stream == null) throw new Exception("LoadAndSerialize : Unable to get a stream from response.");
try
{
instance = Activator.CreateInstance<T>();
}
catch (Exception e)
{
throw new Exception(string.Format("LoadAndSerialize : Unable to create and instance of '{0}' (no parameterless constructor?).", typeof(T).Name), e);
}
try
{
serializer = new DataContractJsonSerializer(instance.GetType());
}
catch (Exception e)
{
throw new Exception(string.Format("LoadAndSerialize : Unable to create serializer for '{0}' (databinding issues?).", typeof(T).Name), e);
}
try
{
instance = (T)serializer.ReadObject(stream);
}
catch (Exception e)
{
throw new Exception(string.Format("LoadAndSerialize : Unable to serialize stream into '{0}'.", typeof(T).Name), e);
}
return instance;
}
Проблема здесь в том, что, хотя все, что может пойти не так, будет поймано и получит несколько значимыйисключение, это беспорядок в значительных пропорциях.
Итак, что, если я зацеплю цепочку вместо этого.Моя следующая попытка заключается в следующем:
private static T LoadAndSerialize<T>(string url)
{
try
{
var uri = new Uri(url);
var request = WebRequest.Create(uri);
var response = request.GetResponse();
var stream = response.GetResponseStream();
var serializer = new DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(stream);
}
catch (ArgumentNullException e)
{
throw new Exception("LoadAndSerialize : Parameter 'url' cannot be null.", e);
}
catch (UriFormatException e)
{
throw new Exception("LoadAndSerialize : Parameter 'url' is malformed.", e);
}
catch (NotSupportedException e)
{
throw new Exception("LoadAndSerialize : Unable to create WebRequest or get response stream, operation not supported.", e);
}
catch (System.Security.SecurityException e)
{
throw new Exception("LoadAndSerialize : Unable to create WebRequest, operation was prohibited.", e);
}
catch (NotImplementedException e)
{
throw new Exception("LoadAndSerialize : Unable to get response from WebRequest, method not implemented?!.", e);
}
catch(NullReferenceException e)
{
throw new Exception("LoadAndSerialize : Response or stream was empty.", e);
}
}
Хотя это, конечно, легче для глаз, я склоняюсь к значению intellisense здесь, чтобы предоставить все исключения, которые могут быть выброшены из метода или класса.Я не уверен, что эта документация на 100% точна, и будет еще более скептически настроена, если некоторые методы будут получены из сборки вне .net framework.В качестве примера, DataContractJsonSerializer не показывает исключений для intellisense.Значит ли это, что конструктор никогда не потерпит неудачу?Могу ли я быть уверен?
Другие проблемы, связанные с этим, заключаются в том, что некоторые методы выдают одно и то же исключение, что усложняет описание ошибки (ту или иную ошибку) и поэтому менее полезно для пользователя./ debugger.
Третий вариант - игнорировать все исключения, кроме тех, которые позволили бы мне выполнить действие, например, попытка повторного подключения.Если url равен null, тогда url равен null, единственная выгода от перехвата - более подробное сообщение об ошибке.
Мне бы очень хотелось увидеть ваши мысли и / или реализации!