抛弃 .NET 经典错误:object null reference , 使用安全扩展方法? 希望对大家有帮助---Bitter.Frame 引用类型的安全转换
还是一样,我不喜欢长篇大论,除非关乎我设计思想领域的文章。大家过来看,都是想节省时间,能用白话表达的内容,绝不长篇大论。能直接上核心代码的,绝不上混淆代码。
长期从事 .NET 工作的人都知道。.NET 的 “object null reference“ 或者“未将对象引用到对象实例”,堪称是.NET 领域的经典错误。 一个错误定位比较麻烦,另外一个容易使程序变得不太健壮。
因此,为了尽量避免此异常的出现,也使的程序变的更加健壮,在我的框架中—Bitter.Frame 框中提供了 安全扩展方法。
涉及到:Int32?,string,Int64?,Long?,DataTime?,Float?,Doubble?,Bool 等类型的转换。
Object 转 Int32?,string,Int64?,Long?,DataTime?,Float?,Doubble?,bool等 可为 NULL 值的安全转换。
Object 转 Int32,string,Int64,Long,DataTime,Float,Doubble ,bool 等 非NULL 值的安全转换。
我们知道:工欲善其事必先利其器,做项目也一样。
如果我们有这样的代码:
Int32? a = null; var b = a.ToString();
上面的过程中就会出现异常:“object null reference“ 或者“未将对象引用到对象实例”,当然上述的代码很常见,单独看上面两行代码,当然很容易发现问题所在,如果 上面代码 a 接收的是一个变量,这个变量又是客户端/或者第三方或者页面传送过来的值,他们没做好控制,或者双方没有做好很好的约定,这个变量值就很有可能为 null. 那么这个错误异常就隐藏的比较深了。
那么我们避免出现这种异常,我们来做个扩展方法,代码如下
/// <summary> /// 对象转string /// </summary> /// <param name="o"></param> /// <returns></returns> public static string ToSafeString(this object o) { return o.ToSafeString(string.Empty); } public static string ToSafeString(this object o, string defaultString) { if (o.IsEmpty()) { return defaultString; } return Convert.ToString(o); }
然后我们 抛弃微软的 ToString()—我暂时称之为非安全转换,我们在使用 object.ToSafeString() 来进行安全转换。
Int32? a = null; var b = a.ToSafeString(“”); //这样就不会抛出异常:object null reference
现在把相关其他类型转换源码贴出来,希望能帮助大家:
public static class ObjectsUtils { /// <summary> /// 比较对象和字符"true","false"是否相同 /// </summary> /// <param name="o"></param> /// <param name="defValue">默认值</param> /// <returns>返回对象和字符"true","false"的比较值(若对象o为null,则返回defValue)</returns> public static bool ToSafeBool(this object o, bool defValue) { if (o != null) { if (string.Compare(o.ToString().Trim().ToLower(), "true", true) == 0) { return true; } if (string.Compare(o.ToString().Trim().ToLower(), "false", true) == 0) { return false; } } return defValue; } /// <summary> /// 比较对象和字符"true","false"是否相同 /// </summary> /// <param name="o"></param> /// <returns>返回对象和字符"true","false"的比较值(若对象o为null,则返回null)</returns> public static bool? ToSafeBool(this object o) { if (o != null) { if (string.Compare(o.ToString().Trim().ToLower(), "true", true) == 0 || o.ToString().Trim() == "1") { return true; } if (string.Compare(o.ToString().Trim().ToLower(), "false", true) == 0 || o.ToString().Trim() == "0") { return false; } } return null; } /// <summary> /// 将当前时间转换成时间戳 /// </summary> /// <param name="o"></param> /// <returns></returns> public static long? ToSafeDataLong(this DateTime? o) { if (!o.HasValue) { return null; } else { System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); return (long)((o.Value - startTime).TotalMilliseconds); } } /// <summary> /// 对象转时间类型 /// </summary> /// <param name="o"></param> /// <param name="defValue">时间默认值</param> /// <returns>返回对象o(若o对象为null或为空,返回defValue值)</returns> public static DateTime ToSafeDateTime(this object o, DateTime defValue) { DateTime result = defValue; if (o == null || string.IsNullOrWhiteSpace(o.ToString())) { return result; } DateTime.TryParse(o.ToString(), out result); return result; } /// <summary> /// 对象转时间类型 /// </summary> /// <param name="o"></param> /// <returns>返回datetime类型(若不能转时间格式或参数为null为空,则返回null)</returns> public static DateTime? ToSafeDateTime(this object o,int exactBit=1) { if (o != null && !string.IsNullOrWhiteSpace(o.ToString())) { DateTime result; if (DateTime.TryParse(o.ToString(), out result)) return result; else return null; } return null; } /// <summary> /// 对象转时间类型 /// </summary> /// <param name="o"></param> /// <returns>返回datetime类型(若不能转时间格式或参数为null为空,则返回null)</returns> public static DateTime? ToSafeDateTime(this object o) { if (o != null && !string.IsNullOrWhiteSpace(o.ToString())) { DateTime result; if (DateTime.TryParse(o.ToString(), out result)) return result; else return null; } return null; } /// <summary> /// 对象转decimal /// </summary> /// <param name="o"></param> /// <param name="defValue">默认返回值</param> /// <returns>返回decimal(若对象为null或超过30长度,则返回默认defvalue)</returns> public static decimal ToSafeDecimal(this object o, decimal defValue) { if ((o == null) || (o.ToString().Length > 30)) { return defValue; } decimal result = defValue; if ((o != null) && Regex.IsMatch(o.ToString(), @"^([-]|[0-9])[0-9]*(\.\w*)?$")) { decimal.TryParse(o.ToString(), out result); } return result; } public static decimal? ToSafeDecimal(this object o) { if (o != null && Regex.IsMatch(o.ToString(), @"^([-]|[0-9])[0-9]*(\.\w*)?$")) { decimal result; decimal.TryParse(o.ToString().Trim(), out result); return result; } return null; } /// <summary> /// 对象转float /// </summary> /// <param name="o"></param> /// <param name="defValue">默认返回值</param> /// <returns>返回float(若对象为null或超过10长度,则返回默认defvalue)</returns> public static float ToSafeFloat(this object o, float defValue) { if ((o == null) || (o.ToString().Length > 10)) { return defValue; } float result = defValue; if ((o != null) && Regex.IsMatch(o.ToString(), @"^([-]|[0-9])[0-9]*(\.\w*)?$")) { float.TryParse(o.ToString(), out result); } return result; } public static float? ToSafeFloat(this object o) { if (o != null && Regex.IsMatch(o.ToString(), @"^([-]|[0-9])[0-9]*(\.\w*)?$")) { float result; float.TryParse(o.ToString().Trim(), out result); return result; } return null; } /// <summary> /// 对象转int /// </summary> /// <param name="o"></param> /// <param name="defaultValue">默认返回值</param> /// <returns>返回int(若对象o为null,或对象无法转int,则返回defaultValue,字符"true"返回1,字符"false"返回0)</returns> public static int ToSafeInt32(this object o, int defaultValue) { if ((o != null) && !string.IsNullOrEmpty(o.ToString()) && Regex.IsMatch(o.ToString().Trim(), @"^([-]|[0-9])[0-9]*(\.\w*)?$")) { int num; string s = o.ToString().Trim().ToLower(); switch (s) { case "true": return 1; case "false": return 0; } if (int.TryParse(s, out num)) { return num; } } return defaultValue; } public static int? ToSafeInt32(this object o) { if ((o != null) && !string.IsNullOrEmpty(o.ToString()) && Regex.IsMatch(o.ToString().Trim(), @"^([-]|[0-9])[0-9]*(\.\w*)?$")) { int num; string s = o.ToString().Trim().ToLower(); switch (s) { case "true": return 1; case "false": return 0; } if (int.TryParse(s, out num)) { return num; } } return null; } /// <summary> /// 对象转Int64(long类型) /// </summary> /// <param name="o"></param> /// <param name="defaultValue"></param> /// <returns></returns> public static long ToSafeInt64(this object o, int defaultValue) { if ((o != null) && !string.IsNullOrEmpty(o.ToString()) && Regex.IsMatch(o.ToString().Trim(), @"^([-]|[0-9])[0-9]*(\.\w*)?$")) { long num; string s = o.ToString().Trim().ToLower(); switch (s) { case "true": return 1; case "false": return 0; } if (long.TryParse(s, out num)) { return num; } } return defaultValue; } public static long? ToSafeInt64(this object o) { if ((o != null) && !string.IsNullOrEmpty(o.ToString()) && Regex.IsMatch(o.ToString().Trim(), @"^([-]|[0-9])[0-9]*(\.\w*)?$")) { long num; string s = o.ToString().Trim().ToLower(); switch (s) { case "true": return 1; case "false": return 0; } if (long.TryParse(s, out num)) { return num; } } return null; } /// <summary> /// 将当前时间转换成时间戳 /// </summary> /// <param name="o"></param> /// <returns></returns> public static DateTime? ToSafeLongDataTime(this long? o) { if (!o.HasValue) { return null; } else if (o.Value == 0) { return null; } else { System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); return (startTime.AddMilliseconds(o.Value)); } } /// <summary> /// 对象转string /// </summary> /// <param name="o"></param> /// <returns></returns> public static string ToSafeString(this object o) { return o.ToSafeString(string.Empty); } public static string ToSafeString(this object o, string defaultString) { if (o.IsEmpty()) { return defaultString; } return Convert.ToString(o); } /// <summary> /// 将字符串转换成全角 /// </summary> /// <param name="o">当前字符串</param> /// <returns></returns> public static string ToSafeSBC(this string o) { if (string.IsNullOrEmpty(o)) { return o; } else { char[] cc = o.ToCharArray(); for (int i = 0; i < cc.Length; i++) { if (cc[i] == 32) { // 表示空格 cc[i] = (char)12288; continue; } if (cc[i] < 127 && cc[i] > 32) { cc[i] = (char)(cc[i] + 65248); } } return new string(cc); } } /// <summary> /// 将字符串转换成半角 /// </summary> /// <param name="o">当前字符串</param> /// <returns></returns> public static string ToSafeDBC(this string o) { if (string.IsNullOrEmpty(o)) { return o; } else { char[] cc = o.ToCharArray(); for (int i = 0; i < cc.Length; i++) { if (cc[i] == 12288) { // 表示空格 cc[i] = (char)32; continue; } if (cc[i] > 65280 && cc[i] < 65375) { cc[i] = (char)(cc[i] - 65248); } } return new string(cc); } } /// <summary> /// 判断对象是否为空 /// </summary> /// <param name="o"></param> /// <returns></returns> private static bool IsEmpty(this object o) { return ((o == null) || ((o == DBNull.Value) || Convert.IsDBNull(o))); } }