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

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

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

上述代码,使用了字符串拼凑的方法,因为使用了多重串联,因此会在内存中创建两个不必要的字符串垃圾副本。

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

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

2、大多数开发人员都不知道内置的验证数据类型的方法,如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;
  13. }

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

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

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

3、自己利用IDisposable接口手动释放内存

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

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

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

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

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

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

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

  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. }
  15. }

在上面的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. }
  12. }

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

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

  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. private void ChildMethod1()
  16. {
  17. try
  18. {
  19. //some implementation
  20. ChildMethod2();
  21. }
  22. catch (Exception exception)
  23. {
  24. //Handle exception
  25. throw;
  26. }
  27. }
  28. private void ChildMethod2()
  29. {
  30. try
  31. {
  32. //some implementation
  33. }
  34. catch (Exception exception)
  35. {
  36. //Handle exception
  37. throw;
  38. }
  39. }
  40. }

如果相同的异常被处理多次,性能开销将会增加。

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

  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. private void ChildMethod1()
  16. {
  17. //some implementation
  18. ChildMethod2();
  19. }
  20. private void ChildMethod2()
  21. {
  22. //some implementation
  23. }
  24. }

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

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

C#中几个经常犯的错误总汇的更多相关文章

  1. 在ABP框架中使用MapTo容易犯的错误

    用自己的话说:MapTo其实就是两个实体间的数据转换.不用像以前那样p.name=p1.name 这样赋值,一旦实体的属性多到十几个以上的时候,这样赋值代码就显得有些臃肿了,如下面: Resource ...

  2. JavaScript中8个容易犯的错误

    这里dbestech针对JavaScript初学者给出一些技巧和列出一些陷阱. 1. 你是否尝试过对数组元素进行排序? JavaScript默认使用字典序(alphanumeric)来排序.因此,[1 ...

  3. python中IF语句容易犯的错误CASE

    python中没有switch   case类似的语句,但是下面的IF语句却与之类似,却又不同: A = B = C = D = E = 1 if A == 1: B=2 elif B ==2: C= ...

  4. 在CMMI推广过程中EPG常犯的错误(转)

    本文转自: http://developer.51cto.com/art/200807/86953.htm 仅用于个人收藏,学习.如有转载,请联系原作者. ---------------------- ...

  5. javascript中易犯的错误有哪些

    javascript中易犯的错误有哪些 一.总结 一句话总结: 比如循环中函数的使用 函数中this的指向谁(函数中this的使用) 变量的作用域 1.this.timer = setTimeout( ...

  6. C#新手常犯的错误

    虽然这篇post的标题是新手常犯的错误,实际上很多有经验的程序员也经常犯这些错误,我整理了一下,就当是笔记.1.遍历List的错误,比如如下代码: List<String> strList ...

  7. 网站移植到linux上后常犯的错误

    常犯的错误 1:gcc库没装或者没装全 表现:没有可用的C编译器 同类错误:提示g++ not found, 解决:出现以上错误,则是因为gcc编译器没装,或者是没装全. 挂载光盘,到Pakeges里 ...

  8. 总结下java经常犯的错误

    编写代码是一种艺术,认识错误是我们代码改进的重要途径之一.以下情况并非大家都能碰到过,但希望提高代码质量的人都引以为戒.以下各种情况,都是初学者经常犯的错误. 1.1       字符串没有判断是否为 ...

  9. 十个JAVA程序员容易犯的错误

    十个JAVA程序员容易犯的错误 1. Array 转 ArrayList 一般开发者喜欢用: List<String> list = Arrays.asList(arr); Arrays. ...

随机推荐

  1. 【Java】【jquery】ajax垃圾问题

    1.暗示HTML.JSP文件本身使用UTF-8格公式 2.HTML的head加: <META http-equiv="Content-Type" content=" ...

  2. 网络资源(2) - Maven视频

    2014_08_23 http://v.youku.com/v_show/id_XNDE2NzM0Nzk2.html Maven最佳实践,公司真实环境实践-私服最佳实践 2014_08_24 http ...

  3. 2014辛星完全解读html第五节

    员,那么肯定会知道什么叫表单,这里我们就介绍一下前台怎样使用表单.表单的使用也是我们编写网页的必须经历的一关.并且,表单也往往是我们站点的漏洞和弱点出现的地方. *************表单**** ...

  4. ACM 入门计划

    acm 本文由swellspirit贡献 ACM • I can accept failure. but I can't accept not trying. Life is often compar ...

  5. (二)spring MVC配置

    使用Maven添加依赖的jar包 <!-- 自动扫描的包名 -->                                                 <mvc:reso ...

  6. UVA Don&#39;t Get Rooked

    主题如以下:  Don't Get Rooked  In chess, the rook is a piece that can move any number of squaresverticall ...

  7. JavaBean中DAO设计模式介绍

    一.信息系统的开发架构 客户层-------显示层-------业务层---------数据层---------数据库 1.客户层:客户层就是client,简单的来说就是浏览器. 2.显示层:JSP/ ...

  8. passenger安装nginx

    1.更换淘宝gem gem sources --remove https://rubygems.org/ gem sources -a https://ruby.taobao.org/ 2.gem安装 ...

  9. 拾人牙慧,浅记一些C++的类

    这两天没事又翻了翻Primer,发现自己上岁数了,记单词能力开始下降,索引把一些简单的例子记下来,把一些肥肉剔除,剩一下骨头,方便今后Ctrl+F.  在此感谢:   http://ticktick. ...

  10. 左右lcm,gcd一些性质

    两个整数a,b  他们的最大公约数为n  最小公倍数为m  则有 a,b都能分解为有限个素数的积               12 = 2^2 * 3^1 * 5^0 , 30 = 2^1 * 3^1 ...