代码陷阱C#

陷阱壹:遍历List

List<String> strList = new List<String>();
for(int i=0; i< strList.Count ; i++)
{
    strList.RemoveAt(i);
}

如果 i = 10 的话,这段代码最后只是删除了5个元素,原因是每次删除一个,列表里之后的所有元素前移,实际上是删一个跳过一个再删一个。
改进:i -=1; 在for循环最后一行处添上、或者 strList.Count 这个替换掉;

陷阱贰:C#常量

public const String str="First Version";

如果你写了一个类库,在里面定义了以上常量,并且在另一个程序里引用了这个类库,如果你修改了这个类库中的常量,发布了一个新的版本,那么在运行之前的程序,你会发现常量还是原来的常量,并没有改变。这是因为在C#编译的时候,常量直接作为元数据嵌入,解决方法是重新编译整个解决方案或者使用属性而不是直接访问常量。

陷阱叁:拆箱和装箱

Int32 a=3;
Object obj = new object();
//这里装箱成功,不会失败
obj=i;
//拆箱一定会失败
Int64 b=(Int64)obj;

改进:

Int64 b =(Int64)(Int32)obj;

陷阱肆:重载 == 运算符出错

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UseOperator
{
  class Program
  {
    static void Main(string[] args)
    {
      Test t1 = new Test();
      t1.MyFun();
      Console.ReadLine();
    }
  }
  class Test
  {
    public void MyFun()
    {
      Test t = new Test();
      if (t == null)
      {
        Console.WriteLine("t为空!");
      }
      else
      {
        Console.WriteLine("t不为空!");
      }
    }
    //存在BUG的重载运算法
    public static bool operator ==(Test t1, Test t2)
    {
      return t2.Equals(t1);
    }
    public static bool operator !=(Test t1, Test t2)
    {
      return !(t1 == t2);
    }
    //覆盖HashCode
    public override int GetHashCode()
    {
      return base.GetHashCode();
    }
    public override bool Equals(object obj)
    {
      return base.Equals(obj);
    }
  }
}

这里的问题在于MyFun中会把NULL传递进 == 运算符函数,导致运行的时候报错,正确的做法是:

public static bool operator ==(Test t1, Test t2)
{
  if ((t2 as object) == null)
  {
    return (t1 as object) == null;
  }
  else
  {
    return t2.Equals(t1);
  }
}

陷阱伍

C#中调用结构的属性或方法必须用new来声明结构变量,否则会出错

陷阱陆

如果params使用多个参数,必须判断参数是否为空,否则程序会有隐藏的Bug

陷阱柒

静态成员在创建第一个实例的时候就会初始化,而且 只被初始化一次,不要乱用静态成员。

陷阱捌

如果使用 ref Object 类型参数接受String类型会出错,这是因为C#要求参数必须使用正确的类型,不加ref是可以的,如果一定要使用ref Object接受String类型参数,可以先转型成Object,再引用传递。

陷阱玖:类的构造函数中永远不要调用虚方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FransferVirtualFunction
{
  class Program
  {
    static void Main(string[] args)
    {
      try
      {
        Child ch = new Child();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
      Console.Read();

    }
  }
  public class Ref
  {
    public string Str = "这是Ref类的一个成员";
  }
  public class Parent
  {
    protected Ref my;
    public Parent()
    {
      my = new Ref();
      //构造方法中调用了虚方法
      Console.WriteLine(GetString());
    }
    //虚方法
    public virtual string GetString()
    {
      return my.Str;    //使用了内部成员
    }
  }
  public class Child : Parent
  {
    private Ref my2;
    public Child()
      : base()
    {
      my2 = new Ref();
    }
    //重写虚方法
    public override string GetString()
    {
      return my2.Str;    //使用了内部成员
    }
  }
}

这里在执行基类的构造函数的时候会执行到派生类的虚方法GetString(),在获取my2.Str的时候抛出异常,因为此时派生类对象还没有被构造。

陷阱拾

在C#和SQL Server通信时要注意NULL的含义,在SQL Server里面这个值代表1900-1-1。SQL Server的空值可以使用DBNull来表示。

补充

1、Math 三角函数 其中的参数为 弧度值,而非角度值。
2、WinForm 中的由相对路径引发的bug:具体可以参考WinForm相对路径的陷阱。
3、使用 xml, json 等序列化后的数据格式传递数据时,如果传递的数据为数值型类型,解析时,最好先将其转为string 然后 tryParse 成相应类型。

你可能感兴趣的:(C#)