不怕犯错误只要能改 C#几个经常犯错误汇总
C#几个经常犯错误汇总
在我们平常编程中 时间久了有时候会形成一种习惯性的思维方式 形成固有的编程风格 但是有些地方是需要斟酌的 即使是一个很小的错误也可能会导致昂贵的代价 要学会善于总结 从错误中汲取教训 尽量不再犯同样错误 注重编程之美 代码的优雅 总结几个平常经常犯的错误 在C#编程中 字符型类型是最容易处理出错的地方 代价是非常昂贵 在 Net Framwork中 字符串是一个相当特别的引用类型 string本省就是一个不可继承的密封类 但是它具有了值类型所应用的特点 但是它在CLR中内存还是保存于托管堆之上 也就是说 当我们每次定义一个字符串类型的时候 就在堆内存中开辟一端内存 而当我们字符串被修改之后 它会创建一个新的内存 注意这里的内存是不连续的 而是通过修改栈内地址引用而拼凑字符串 不会改变源字符串在内存中的地址 所以有些程序员总是喜欢使用这样的方法格式化字符串 string SelectText= select * from +TableName+ where UserName= +Name+ ; 上述代码 使用了字符串拼凑的方法 因为使用了多重串联 因此会在内存中创建两个不必要的字符串垃圾副本 其实在C#中 已经为我们提供了StringBuilder和String Fromat来解决此问题 虽然他们可以实现同样的功能 但是他们有质的变化 StringBuilder在内存中开辟的是一段连续内存 当增加新字符串时候 它会在栈中指向的同一个堆内存中连续存放字符 这就形成了性能的提升 所以我们将上面代码改成 string SelectText=string Format( select * from { } where UserName={ } TableName Name) 大多数开发人员都不知道内置的验证数据类型的方法 如System Int 因此很多人都是自己实现的 其实这是不妥的 因为这些基本类型中都存在自己固有的类型验证方法 下面这个就是自己实现验证的一个字符串是否是数值的代码public bool CheckIfNumeric(string value) { bool IsNumeric=true; try { int i=Convert ToInt (value); } catch(FormatException excepiton) { IsNumeric=false; } return IsNumeric; }
虽然使用了try catch语句 这不是最佳的做法 更好的方法是下面使用Int TryParse
int output= ; bool IsNumeric=int TryParse(value out output);
int TryParse是更快 更简洁的方法
自己利用IDisposable接口手动释放内存
在 NET Framework中 对象的处理和使用一样重要 理想的方法是在使用完对象的时候 在类中实现IDisposable接口中的dispose方法进行内存的释放 当然在 Net本身提供的垃圾回收机制(GC)中就提供了这样的功能 在我们实例化类对象时 在类本身的析构函数中会调用dispose方法 GC在各级内存堆满的情况下 自动检查对象使用情况 去相应的释放内存 但是运行在非托管平台上的方法 需要我们自己手动释放内存 比如我们常见的SqlConnection对象 也就有了下面的创建 使用和处理方法
public void DALOneMethod() { SqlConnection connection=null; try { connection =new SqlConnection( ); connection Open(); //sqlmand run } catch(Exception exception) { // manager exception } finally { connection Close(); connection Disopse(); } }
上述代码是大部分程序员会出现的代码 乍看没啥问题 连接处理在最后一个代码中被明确调用 但是如果发生了一个异常 catch代码块就被执行 然后再执行最后一个代码块处理连接 因此在最后一个代码块执行之前 连接将一直留在内存中 大部分我们会在此处记录错误 一般涉及到IO操作 如果延时时间比较长的话 这个连接将在内存时间长时间停留 我们一个原则就是当对象不再使用的时候我们里面释放资源
我们采用程序逻辑域来处理这个问题会更好
public void DALOneMethod() { using(SqlConnction connection=new SqlConnection( )) { connction Open() // do SUAD } }

当使用using代码快时 对象上的dispose()方法将在执行推出逻辑域的时候调用 这样就保证了SqlConnection的资源处理被尽早释放 当然这个方法也适用于实现IDisposable接口的类 当时个人不推荐这样做 在非常有把握的情况下可以手动释放 但是没把握还是叫给 net系统释放 因为本身类的析构函数就实现这个方法 当我们自己重写后 反而会导致系统误以为你自己定义了方法 而推迟释放资源 有兴趣可以研究下GC运行本质 假如能在第一代被释放的内存 如果我们重写dispose方法反而推迟到第二代内存堆中释放 显然是不可取的
学会合理的管理公共变量 我们在系统中经常会滥用公共变量 没有做到合适的封装好
static void Main(string[] args) { MyAccount account=new MyAccount(); //这地方不能随便的调用account里面的字段进行更改 但是缺改了 account AccountNumber= ddddddddd ; Console ReadKey(); } public class MyAccount { public string AccountNumber; public MyAcctount() { AccountNumber= ssssssssssssss ; } }
在上面的MyAccount类中生命了一个AccountNumber公共变量 理想情况下 AccountNumber应该是只读的 不能让外界修改 但是这里MyAccount类却没有对它做任何控制
声明公共做法应该是使用属性 如
public class MyAccount { private stirng _accountNumber; public string AccountNumber { get { return _accountNumber; } } public MyAccount() { _accountNumber= dddddddd ; } }
这里我们封装了AccountNumber公共变量 它变成了只读 不能由调用者类进行修改
嵌套的异常处理 有的开发人员喜欢在方法末尾加上处理的嵌套方法 如
public class NestedExceptionHandling { public void MainMethod() { try { //some implementation ChildMethod (); } catch (Exception exception) { //Handle exception } } private void ChildMethod () { try { //some implementation ChildMethod (); } catch (Exception exception) { //Handle exception throw; } } private void ChildMethod () { try { //some implementation } catch (Exception exception) { //Handle exception throw; } } }
如果相同的异常被处理多次 性能开销将会增加
我们的解决方法是让异常处理方法独立开来 如
public class NestedExceptionHandling { public void MainMethod() { try { //some implementation ChildMethod (); } catch(Exception exception) { //Handle exception } } private void ChildMethod () { //some implementation ChildMethod (); } private void ChildMethod () { //some implementation } } lishixinzhi/Article/program/ASP/201311/21846