C#几个常常犯错误汇总

在咱们日常编程中,时间久了有时候会造成一种习惯性的思惟方式,造成固有的编程风格,可是有些地方是须要斟酌的,即便是一个很小的错误也可能会致使昂贵的代价,要学会善于总结,从错误中汲取教训,尽可能再也不犯一样错误,注重编程之美,代码的优雅,总结几个日常常常犯的错误。html

一、在C#编程中,字符型类型是最容易处理出错的地方,代价是很是昂贵,在.Net Framwork中,字符串是一个至关特别的引用类型,string本省就是一个不可继承的密封类,可是它具备了值类型所应用的特色,可是它在CLR中内 存仍是保存于托管堆之上,也就是说,当咱们每次定义一个字符串类型的时候,就在堆内存中开辟一端内存,而当咱们字符串被修改以后,它会建立一个新的内存, 注意这里的内存是不连续的,而是经过修改栈内地址引用而拼凑字符串,不会改变源字符串在内存中的地址,因此有些程序员老是喜欢使用这样的方法格式化字符 串:程序员

  1. string  SelectText="select * from "+TableName+" where UserName='"+Name+"'"

上述代码,使用了字符串拼凑的方法,由于使用了多重串联,所以会在内存中建立两个没必要要的字符串垃圾副本。sql

其实在C#中,已经为咱们提供了StringBuilder和String.Fromat来解决此问题,虽然他们能够实现一样的功能,可是他们有质 的变化,StringBuilder在内存中开辟的是一段连续内存,当增长新字符串时候,它会在栈中指向的同一个堆内存中连续存放字符,这就造成了性能的 提高。因此咱们将上面代码改为:编程

  1. string SelectText=string.Format("select  *  from {0} where UserName={1}",TableName,Name); 

二、大多数开发人员都不知道内置的验证数据类型的方法,如System.Int32,所以不少人都是本身实现的,其实这是不妥的,由于这些基本类型中都存在本身固有的类型验证方法,下面这个就是本身实现验证的一个字符串是不是数值的代码:函数

  1. public bool CheckIfNumeric(string value)  
  2. {  
  3.     bool IsNumeric=true;  
  4.     try 
  5.      {  
  6.            int i=Convert.ToInt32(value);  
  7.      }  
  8.      catch(FormatException excepiton)  
  9.      {  
  10.            IsNumeric=false;  
  11.      }  
  12.      return IsNumeric;  

虽然使用了try catch语句,这不是最佳的作法,更好的方法是下面使用Int.TryParse;post

  1. int output=0;  
  2. bool IsNumeric=int.TryParse(value,out output); 

int.TryParse是更快、更简洁的方法。性能

三、本身利用IDisposable接口手动释放内存大数据

在.NET Framework中,对象的处理和使用同样重要,理想的方法是在使用完对象的时候,在类中实现IDisposable接口中的dispose方法进行内 存的释放,固然在.Net自己提供的垃圾回收机制(GC)中就提供了这样的功能,在咱们实例化类对象时,在类自己的析构函数中会调用dispose方 法,GC在各级内存堆满的状况下,自动检查对象使用状况,去相应的释放内存,可是运行在非托管平台上的方法,须要咱们本身手动释放内存,好比咱们常见的 SqlConnection对象,也就有了下面的建立、使用和处理方法:ui

  1. public void  DALOneMethod()  
  2. {  
  3.     SqlConnection  connection=null;  
  4.     try 
  5.      {  
  6.           connection =new SqlConnection("。。。。。。。。。。。");  
  7.           connection.Open();  
  8.           //sqlcommand。。run  
  9.  
  10.      }  
  11.      catch(Exception exception)  
  12.      {  
  13.              // manager exception  
  14.      }  
  15.      finally 
  16.      {  
  17.             connection.Close();  
  18.             connection.Disopse();  
  19.      }  

上述代码是大部分程序员会出现的代码,乍看没啥问题,链接处理在最后一个代码中被明确调用,可是若是发生了一个异常,catch代码块就被执行,然 后再执行最后一个代码块处理链接,所以在最后一个代码块执行以前,链接将一直留在内存中,大部分咱们会在此处记录错误,通常涉及到IO操做,若是延时时间 比较长的话,这个链接将在内存时间长时间停留。咱们一个原则就是当对象再也不使用的时候咱们里面释放资源。spa

咱们采用程序逻辑域来处理这个问题会更好:

  1. public void  DALOneMethod()  
  2. {  
  3.     using(SqlConnction  connection=new SqlConnection("。。。。。。。"))  
  4.      {  
  5.          connction.Open();  
  6.       // do SUAD  
  7.      }  

当使用using代码快时,对象上的dispose()方法将在执行推出逻辑域的时候调用,这样就保证了SqlConnection的资源处理被尽 早释放,固然这个方法也适用于实现IDisposable接口的类,当时我的不推荐这样作,在很是有把握的状况下能够手动释放,可是没把握仍是叫 给.net系统释放,由于自己类的析构函数就实现这个方法,当咱们本身重写后,反而会致使系统误觉得你本身定义了方法,而推迟释放资源,有兴趣能够研究下 GC运行本质,假如能在第一代被释放的内存,若是咱们重写dispose方法反而推迟到第二代内存堆中释放,显然是不可取的。

四、学会合理的管理公共变量,咱们在系统中常常会滥用公共变量,没有作到合适的封装好。

  1. static  void Main(string[]  args)  
  2. {  
  3.             MyAccount  account=new MyAccount();  
  4.            //这地方不能随便的调用account里面的字段进行更改,可是缺改了  
  5.         account.AccountNumber="ddddddddd";  
  6.            Console.ReadKey();  
  7. }  
  8. public class MyAccount  
  9. {  
  10.           public  string AccountNumber;  
  11.           public  MyAcctount()  
  12.           {  
  13.                 AccountNumber="ssssssssssssss";  
  14.           }  

在上面的MyAccount类中生命了一个AccountNumber公共变量,理想状况下,AccountNumber应该是只读的,不能让外界修改,可是这里MyAccount类却没有对它作任何控制。

声明公共作法应该是使用属性,如:

  1. public  class  MyAccount  
  2. {  
  3.    private stirng _accountNumber;  
  4.    public  string AccountNumber  
  5.    {  
  6.         get {  return  _accountNumber;  }  
  7.    }  
  8.    public  MyAccount()  
  9.    {  
  10.           _accountNumber="dddddddd";  
  11.    }  

这里咱们封装了AccountNumber公共变量,它变成了只读,不能由调用者类进行修改。

五、嵌套的异常处理,有的开发人员喜欢在方法末尾加上处理的嵌套方法,如

  1. public class NestedExceptionHandling  
  2.   {  
  3.       public void MainMethod()  
  4.       {  
  5.           try 
  6.           {  
  7.               //some implementation  
  8.               ChildMethod1();  
  9.           }  
  10.           catch (Exception exception)  
  11.           {  
  12.               //Handle exception  
  13.           }  
  14.       }  
  15.     
  16.       private void ChildMethod1()  
  17.       {  
  18.           try 
  19.           {  
  20.               //some implementation  
  21.               ChildMethod2();  
  22.           }  
  23.           catch (Exception exception)  
  24.           {  
  25.               //Handle exception  
  26.            throw;  
  27.     
  28.           }  
  29.       }  
  30.     
  31.       private void ChildMethod2()  
  32.       {  
  33.           try 
  34.           {  
  35.               //some implementation  
  36.           }  
  37.           catch (Exception exception)  
  38.           {  
  39.               //Handle exception  
  40.               throw;  
  41.           }  
  42.       }  
  43.   } 

若是相同的异常被处理屡次,性能开销将会增长。

咱们的解决方法是让异常处理方法独立开来,如:

  1. public class NestedExceptionHandling  
  2.   {  
  3.       public void MainMethod()  
  4.       {  
  5.           try 
  6.           {  
  7.               //some implementation  
  8.               ChildMethod1();  
  9.           }  
  10.           catch(Exception exception)  
  11.           {  
  12.               //Handle exception  
  13.           }  
  14.       }  
  15.     
  16.       private void ChildMethod1()  
  17.       {  
  18.           //some implementation  
  19.           ChildMethod2();  
  20.       }  
  21.     
  22.       private void ChildMethod2()  
  23.       {  
  24.           //some implementation  
  25.       }  
  26.   } 

六、大数据量上使用Dataset和DataReader混用,当单表数据量很大的状况,使用DataSet是一种很不明智的选择,应为 DataSet是以DataTable内存形式存放数据量,一次性将数据拖入内存,当数据很大的状况下,这种方式是很吃内存的,相比 DataSer,DataReader就显得优雅不少,它是每次读取一条数据,而后轮询调用机制,可是也有它的弊端,就是相对长链接,可是对内存消耗而言 这是有利的,固然DataSet在大部分应用场景下也是有本身的优势,充分解耦、一次性操做、领域模型操做等方面,二者分状况分场景而用,这里只是稍微提 提,根据场景分析区别。

原文连接:http://www.cnblogs.com/zhijianliutang/archive/2012/03/20/2407688.html

相关文章
相关标签/搜索