分享一下我的【返回自定义返回值和错误信息】的方法

dodducs 2012-07-30 10:04:19
刚看了个帖子,那个LZ在鄙视用out和ref来返回错误信息。

好吧,其实out和ref我只是在调用一个方法有不少于1个返回值时又不想因此而创建一个类时才使用的。

下面讲下我目前使用的返回错误信息的方法:

在非UI界面的方法中,我会尽量不用catch来捕获异常,除非一些特殊情况,比如这个方法会进行很多个地方的修改,而在修改到其中某一条发现无法修改时需要回滚操作,才会用catch捕获住将修改回滚。但还是会抛出异常!

去年的一个项目中我使用了两种方法。具体原因不详细描述了,直接给大家看代码吧。


1.第一个作为程序内部的错误码返回。 -1 是正确的带有返回值的。可能有人觉得正确的干嘛抛出异常呢?
和项目的特殊性有关,这个软件是提供 lua api 的,lua需要将脚本中返回值传出只能通过这个方法,因为其他的方法已经被我自己做的 lua 虚拟机给拦截住了。在此不多讨论合理性,蛮复杂的。这个只是一个简易的自定义返回异常。

使用方法:只要在最外层代码 catch(CustomReturnCode crc) 就可以了。


public class CustomReturnCode : Exception
{
private int _code;

public int Code
{
get { return _code; }
}

private string _message;

public override string Message
{
get
{
return _message;
}
}

public CustomReturnCode()
: base()
{

}

public CustomReturnCode(string message)
: base(message)
{
_code = -1;
_message = message;
}

public CustomReturnCode(int code, string message)
{
_code = code;
_message = message;
}

public void SetReturnCode(int code, string message)
{
_code = code;
_message = message;
}

}



2.同第一个一样我不详细讲为什么这么做了,只是提供另一个思路。
这个返回信息其实不是抛出异常,而是接受方,或者说你的调用函数自己判断是否为异常的。

使用方法:

CommandResult cr = CommandResult.Success;

//获得描述
EnumHelper.GetEnumDescription(cr);
//获得枚举int值
(int)cr;



//返回执行结果的枚举
public enum CommandResult
{
[Description("成功")]
Success = 1,

[Description("Url太长")]
UrlTooLong = 2,
};

//枚举功能辅助
public static class EnumHelper
{
public static string GetEnumDescription(object enumSubitem)
{
enumSubitem = (Enum)enumSubitem;
string strValue = enumSubitem.ToString();

FieldInfo fieldinfo = enumSubitem.GetType().GetField(strValue);

if (fieldinfo != null)
{

Object[] objs = fieldinfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

if (objs == null || objs.Length == 0)
{
return strValue;
}
else
{
DescriptionAttribute da = (DescriptionAttribute)objs[0];
return da.Description;
}
}
else
{
return "";
}
}
}
...全文
441 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
dodducs 2012-07-31
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]
楼主的例子很特殊,一般情况下,尽量避免用异常来返回正确信息,因为异常开销比较大。

第2个方法无非是返回一个用户自定义的对象。给枚举加个description属性当然并非不可,但感觉意义不大,本来,Success, UrlTooLong的意思已经够清楚了。

至于楼主说:
“在非UI界面的方法中,我会尽量不用catch来捕获异常,除非一些特殊情况,比如这个方法会进行很多个地方的修改,而在……
[/Quote]

啊,,好囧,我这个是WCF的方法。。不知道别的地方好不好用。。。发出来才想到
dodducs 2012-07-31
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

楼主的例子很特殊,一般情况下,尽量避免用异常来返回正确信息,因为异常开销比较大。

第2个方法无非是返回一个用户自定义的对象。给枚举加个description属性当然并非不可,但感觉意义不大,本来,Success, UrlTooLong的意思已经够清楚了。

至于楼主说:
“在非UI界面的方法中,我会尽量不用catch来捕获异常,除非一些特殊情况,比如这个方法会进行很多个地方的修改,而……
[/Quote]

嗯,我来解释为什么返回正确信息,因为是http而且是局域网,所以开销可以忽略。

第二个方法加上Description属性,是因为处理对方需要中文描述的时候使用。

最后一个不是不捕获异常,我说了在非UI界面方法中尽量不catch。这个说法其实只是想说除了UI界面,不要拦截异常,要尽量的向顶层暴露异常,而这个异常可以是framework的,也可以是Lib、Logic等截获的异常,然后为了更改为自定义异常。但是不要catch住后就不向顶层汇报。因为你无法知道UI需要做什么。或许UI还做了一些还原操作呢?

所有Log的输出我也会尽量放在UI下,个别情况除外,可能有人会觉得放在UI不好定位问题。
其实这个没那么复杂,下面代码可以解决,自己修改下就可以了。


private void PrintToLog()
{
if (!_isWriteLog)
{
return;
}

if (!_isRegistedLog)
{
switch (ConfigurationManager.AppSettings["LogType"])
{
case "None":
_isWriteLog = false;
return;
case "Console":
Logger.RegisterConsoleListener();
break;
case "File":
Logger.RegisterTextWriterListener();
break;
default:
_isWriteLog = false;
return;
}
_isRegistedLog = true;
}

StackTrace st = new StackTrace(false);
StackFrame sf = st.GetFrame(1);

//提供方法执行的上下文环境
OperationContext context = OperationContext.Current;
//获取传进的消息属性
MessageProperties properties = context.IncomingMessageProperties;

//获取消息发送的远程终结点IP和端口
RemoteEndpointMessageProperty endpoint = properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;

Logger.Info(string.Format("IP - {0}:{1},请求方法:{2}", endpoint.Address, endpoint.Port, sf.GetMethod().Name));
}
dodducs 2012-07-30
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

支持新思路
[/Quote]

这个不新啊,我见过很多人在用。返回自定义异常蛮普遍的。
  • 打赏
  • 举报
回复
楼主的例子很特殊,一般情况下,尽量避免用异常来返回正确信息,因为异常开销比较大。

第2个方法无非是返回一个用户自定义的对象。给枚举加个description属性当然并非不可,但感觉意义不大,本来,Success, UrlTooLong的意思已经够清楚了。

至于楼主说:
“在非UI界面的方法中,我会尽量不用catch来捕获异常,除非一些特殊情况,比如这个方法会进行很多个地方的修改,而在修改到其中某一条发现无法修改时需要回滚操作,才会用catch捕获住将修改回滚。但还是会抛出异常!


不很理解。不捕获异常,如何打log?如果没有log,出了问题如何排错?

fsstolw 2012-07-30
  • 打赏
  • 举报
回复
支持新思路
dodducs 2012-07-30
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
支持分享
[/Quote]

我倒,我的沙发没了。
dodducs 2012-07-30
  • 打赏
  • 举报
回复
第一种可以将 message 的 string 类型改成 object
这样可以应付更多正确的返回值 code = -1 的使用程度会扩大很多。
但是不推荐,毕竟用异常返回正确信息,如非必要,看起来真的很怪。



第二种方法因为用到了反射,所以提醒不要大规模使用。以免影响性能。
但是第二种方法比较友好,毕竟不是异常嘛。

沙发我自己的了。
bdmh 2012-07-30
  • 打赏
  • 举报
回复
支持分享

110,476

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧