下面这几个,是在实际开发或阅读中发现的一些问题,有些甚至是有很多年开发人员写出的代码,也是很多人经常犯的错误。各位可以看看,你有没有躺着中枪。


第一个,对整型变量进行非null判断。

// a 是int型 (不是int?)
if(a != null){
    //操作
}

 

个人点评:无意义判断,值类型永远不可能为null。

第二个,用static来保持页面回发

static int id;
protected void Page_Load(object sender, EventArgs e)
{
    if (Request.QueryString["ID"] != null && Request.QueryString["ID"].ToString() != "")
    {
        id = Convert.ToInt32(Request.QueryString["ID"].ToString());
    }
}

 

个人点评:这个不解释,不知道怎么说。但最近还真就遇到了,而且也不是什么小项目,WebForm无服务器控件开发。

第三个,用编程方式绑定数据控件时,数据源为DataSet时判断null而不判读DataSet内的Tables数。

DataSet ds = bll.GetList(); 
if (ds != null)
{
    Repeater1.DataSource = ds;
    Repeater1.DataBind();
}

 

个人点评:当bll.GetList()返回的DataSet非null但里面没有包含数据表时,执行DataBind()方法时会报HttpException异常(IListSource 不包含任何数据源)。正确写法应该是

DataSet ds = bll.GetList();
if (ds != null && ds.Tables.Count > 0)
{
    Repeater1.DataSource = ds;
    Repeater1.DataBind(); 
}
//
DataSet ds = bll.GetList()??new DataSet();
if (ds.Tables.Count > 0)
{
    Repeater1.DataSource = ds;
    Repeater1.DataBind(); 
}

 

第四个,用编程方式绑定数据控件时,数据源为DataTable或List<T>时判断null。

DataTable dt = bll.GetList();
if (dt!=null)
{
    Repeater1.DataSource = dt;
    Repeater1.DataBind();
}

 

个人点评:无意义判断,下面的写法没有任何问题,即使dt=null

DataTable dt = bll.GetList();
Repeater1.DataSource = dt;
Repeater1.DataBind();

 

第五个

Model m = new Model(); 
m = bll.GetModel(id);
m.name;

 

个人点评:以为只要声明时不为null,后面就不需要做非空非null判断了。万一第二步BLL层返回的model就为null呢?

第六个,在Repeater1_ItemDataBound中写这样的代码

Label lblPMID = (Label)e.Item.FindControl("lblPMID");
if (lblPMID.Text != "")
{
    //操作
}

 

个人点评:低效,无意义判断,很可能出现NullReferenceException(未将对象引用设置到对象的实例)异常。
正确写法:

Label lblPMID = e.Item.FindControl("lblPMID") as Label;
if (lblPMID!=null && lblPMID.Text != "") //视里面使用情况决定是否判断lblPMID.Text为“”或空白
{
    //操作
}

 

第七个

string txtName = Request["txtName"] == null ? "" : Request["txtName"].ToString();
string strWhere += "and ID=" + userId + ""; //userId是int
if (txtName != "")
{
    strWhere += " and NAME='" + txtName + "'"; 
}
strWhere += " order by id desc";
//项目本身都是采用参数化查询的,这里是一些暴露给Web层的高级查询条件。

 

个人点评:1、值类型和字符串拼接会隐式装箱,2、SQL注入危险。正确做法是userId.ToString()并且过滤txtName中特殊字符,限制字符串长度。
注意,拼接SQL时过滤字符串并不能完全防止SQL注入,但很多时候在高级查询时拼接SQL是最简单也是最方便的,这时候过滤不应该只过滤一些指定的特殊字符,
比如只过滤单引号,等号,大于/小于/等于,空格,括号之类的危险字符。应该对除中文字符、英文字母、和数字外的所有字符全部过滤掉(视情况而定)。
并且严格限制字符串长度,一般查询时输入的关键字不会太长,如果用户输入的有空格,就拆分成多个条件。这样能尽可能的减小SQL注入的机会。


最后,给大家分享几个小经验,虽说有些只是语法糖,但却可以帮助我们更高效编写或阅读代码。

一、引用类型的null值很麻烦,因为类型为null时使用点运算符 (.)会报异常,所以经常要做非null判断,可以用?? null 合并运算符减少代码量。例如:

//写法一
int ID;
if (Request.Form["ID"] != null && Request.Form["ID"].ToString() != "")
{
ID = Convert.ToInt32(Request.Form["ID"].ToString());
}

//写法二
int id;
if (int.TryParse(Request.Form["ID"]??"",out id))
{

}

//方法一
string userName2=string.Empty;
if (Session["userName"]!=null)
{
    userName2 = Session["userName"].ToString();
}

//方法二
string userName1 = Session["userName"] == null ? "" : Session["userName"].ToString();

//方法三
string userName = (Session["userName"] ?? "").ToString();

 

二、Web项目中的所有Session或cookie最好统一放到一个类中管理。最重要的目的是把Session中索引名独立出来管理,也就是除了本类外的所有页面都不要输入Session名。
可能用语言表达不够直白,直接上代码。
看到很多人是这样,包括网上流行的一些很常见的辅助类库。

 1     /// <summary>
 2     /// Session 操作类
 3     /// 1、GetSession(string name)根据session名获取session对象
 4     /// 2、SetSession(string name, object val)设置session
 5     /// </summary>
 6     public class SessionHelper
 7     {
 8         /// <summary>
 9         /// 根据session名获取session对象
10         /// </summary>
11         /// <param name="name"></param>
12         /// <returns></returns>
13         public static object GetSession(string name)
14         {
15             return HttpContext.Current.Session[name];
16         }
17         /// <summary>
18         /// 设置session
19         /// </summary>
20         /// <param name="name">session 名</param>
21         /// <param name="val">session 值</param>
22         public static void SetSession(string name, object val)
23         {
24             HttpContext.Current.Session.Remove(name);
25             HttpContext.Current.Session.Add(name, val);
26         }
27         /// <summary>
28         /// 检测session是否存在
29         /// </summary>
30         /// <param name="name"></param>
31         /// <returns></returns>
32         public static bool CheckSession(string name)
33         {
34             try
35             {
36                 if (GetSession(name) == null)
37                 {
38                     return false;
39                 }
40                 else
41                 {
42                     return true;
43                 }
44             }
45             catch
46             {
47                 return false;
48             }
49         }
50     }
View Code

相关文章: