c#异常处理,实例。你会怎么做?
我试图更好地处理异常,但当我尽力捕捉异常时,我觉得我的代码变得非常难看、不可读和混乱。我想看看其他人是如何通过给出一个实际的例子和比较解决方案来实现这一点的 我的示例方法从URL下载数据,并尝试将其序列化为给定类型,然后返回一个填充了数据的实例 首先,毫无例外地处理:c#异常处理,实例。你会怎么做?,c#,exception-handling,C#,Exception Handling,我试图更好地处理异常,但当我尽力捕捉异常时,我觉得我的代码变得非常难看、不可读和混乱。我想看看其他人是如何通过给出一个实际的例子和比较解决方案来实现这一点的 我的示例方法从URL下载数据,并尝试将其序列化为给定类型,然后返回一个填充了数据的实例 首先,毫无例外地处理: private static T LoadAndSerialize<T>(string url) { var uri = new Uri(url);
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);
}
private static T LoadAndSerialize(字符串url)
{
var uri=新的uri(url);
var request=WebRequest.Create(uri);
var response=request.GetResponse();
var stream=response.GetResponseStream();
var result=Activator.CreateInstance();
var serializer=newdatacontractjsonserializer(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(字符串url)
{
Uri;
网络请求请求;
网络响应;
溪流;
T例;
DataContractJsonSerializer序列化程序;
尝试
{
uri=新的uri(url);
}
捕获(例外e)
{
抛出新异常(“LoadAndSerialize:参数“url”格式错误或丢失。”,e);
}
尝试
{
request=WebRequest.Create(uri);
}
捕获(例外e)
{
抛出新异常(“LoadAndSerialize:无法创建WebRequest.”,e);
}
尝试
{
response=request.GetResponse();
}
捕获(例外e)
{
抛出新异常(string.Format(“LoadAndSerialize:从主机“{0}.”,uri.host获取响应时出错),e);
}
if(response==null)抛出新异常(string.Format(“LoadAndSerialize:没有来自主机“{0}.”的响应,uri.host));
尝试
{
stream=response.GetResponseStream();
}
捕获(例外e)
{
抛出新异常(“LoadAndSerialize:无法从响应获取流。”,e);
}
if(stream==null)抛出新异常(“LoadAndSerialize:无法从响应中获取流”);
尝试
{
instance=Activator.CreateInstance();
}
捕获(例外e)
{
抛出新异常(string.Format(“LoadAndSerialize:无法创建“{0}”(无参数构造函数?)”的实例),typeof(T.Name),e);
}
尝试
{
serializer=newDataContractJSonSerializer(instance.GetType());
}
捕获(例外e)
{
抛出新异常(string.Format(“LoadAndSerialize:无法为“{0}”(数据绑定问题?)”创建序列化程序),typeof(T.Name),e);
}
尝试
{
instance=(T)serializer.ReadObject(流);
}
捕获(例外e)
{
抛出新异常(string.Format(“LoadAndSerialize:无法将流序列化为“{0}.”,typeof(T.Name),e);
}
返回实例;
}
这里的问题是,尽管所有可能出错的事情都会被发现,并给出一个有意义的例外,但这是一场规模巨大的混乱盛会
那么,如果我用链子代替接球呢。我的下一个尝试是:
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);
}
}
private static T LoadAndSerialize(字符串url)
{
尝试
{
var uri=新的uri(url);
var request=WebRequest.Create(uri);
var response=request.GetResponse();
var stream=response.GetResponseStream();
var serializer=newdatacontractjsonserializer(typeof(T));
return(T)serializer.ReadObject(stream);
}
捕获(e)
{
抛出新异常(“LoadAndSerialize:参数“url”不能为null。”,e);
}
捕获(尿酸盐)
{
抛出新异常(“LoadAndSerialize:参数“url”格式不正确。”,e);
}
捕获(不支持例外e)
{
抛出新异常(“LoadAndSerialize:无法创建WebRequest或获取响应流,操作不受支持。”,e);
}
捕获(System.Security.SecurityException e)
{
抛出新异常(“LoadAndSerialize:无法创建WebRequest,操作被禁止。”,e);
}
捕获(未实现异常e)
{
抛出新异常(“LoadAndSerialize:无法从WebRequest获取响应,方法未实现?!”,e);
}
捕获(NullReferenceException e)
{
抛出新异常(“LoadAndSerialize:响应或流为空。”,e);
}
}
虽然从外观上看确实更容易,但我在这里非常倾向于使用intellisense来提供可能从方法或类抛出的所有异常。我不相信这个文档是100%准确的,如果一些方法来自.net框架之外的程序集,我会更加怀疑。例如,DataContractJsonSerializer在intellisense上没有显示任何异常。这是否意味着构造函数永远不会失败?我能肯定吗
与此相关的其他问题是,一些方法抛出相同的异常,这使得错误更难描述(这个或这个或这个出错),并且
public IMethodReturn Invoke(IMethodInvocation input,
GetNextHandlerDelegate getNext)
{
var methodReturn = getNext().Invoke(input, getNext);
if (methodReturn.Exception != null)
{
// exception was encountered...
var interceptedException = methodReturn.Exception
// ... do whatever you need to do, for instance:
if (interceptedException is ArgumentNullException)
{
// ... and so on...
}
}
}