尽量避免少的装箱拆箱:
string a = "a" + 0; string b = "a" + 0.ToString(); //高效 //ToString()是直接通过操作内存来完成int到string的转换,效率比装箱高很多
ArrayList和List<T>,尽量使用List而不用ArrayList,ArrayList会进行拆箱装箱操作,存值会转换成Object存储(装箱),取值再转换成对应类型(拆箱);List<T>就不会
字符串大量操作使用StringBuilder
区别const 和 readonly的使用方法
const效率高,编译期常量,天然就是static,不能再前面增加static关键字修饰.经过编译器编译之后.在代码中引用const的地方会用const变量所对应的实际值来代替.只能修饰基元类型,枚举类型或字符串类型
readonly效率可以,运行时常量,第一次被赋值后将不可改变,修饰没有限制readonly属于类实例的成员,要使他成为类的成员,需要在前面加上static,这样就可以直接使用类名调用.(构造函数,变量初始化都可以赋值)
重载运算符
class Test { public int par; public static Test operator +(Test a,Test b) { a.par += b.par; return a; }
}
== 和 Equals
Equals用于引用类型的相等性比较,==用于值类型的相等性比较
如果用来比较的两个变量所包含的数值相等,那么将其定义为“值相等”;
如果比较的两个变量引用的是同一内存,那么将其定义为“引用相等”。
dynamic与var (dynamic没搞懂)
dynamic是FrameWork4.0的新特性。dynamic的出现让C#具有了弱语言类型的特性。编译器在编译的时候不再对类型进行检查,编译期默认dynamic对象支持你想要的任何特性。比如,即使你对GetDynamicObject方法返回的对象一无所知,你也可以像如下那样进行代码的调用,编译器不会报错:
Console.WriteLine(dynamicObject.Name);
Console.WriteLine(dynamicObject.SampleMethod());
实际上,var和dynamic完全是两个概念,根本不应该放在一起做比较。var实际上是编译期抛给我们的“语法糖”,一旦被编译,编译期会自动匹配var 变量的实际类型,并用实际类型来替换该变量的申明,这看上去就好像我们在编码的时候是用实际类型进行申明的。而dynamic被编译后,实际是一个object类型,只不过编译器会对dynamic类型进行特殊处理,让它在编译期间不进行任何的类型检查,而是将类型检查放到了运行期。
foreach不支持循环时增删操作
如果在foreach中增/删某一元素,则会抛出异常。
原因:foreach循环使用了迭代器进行集合的遍历,它在FCL提供的迭代器内部维护了一个对集合版本的控制。
集合版本:简单来说就是一个整型变量,任何对集合的增删操作都会使版本号+1。
foreach循环会调用MoveNext方法来便利元素,MoveNext方法内部会进行版本号的检测,一旦版本号变动,就会抛异常。
必要时将不再使用的对象引用赋值为null
delegate与event
public delegate void ActionCall(); public event ActionCall call; //委托可以赋值(=)和绑定(+= -=),事件只能绑定(+= -=) //事件在本类可以调用,其他类中不能调用;
拓展方法:不改变原类,给类添加方法
public class Test { public void Action() { } } //扩展方法必须在静态类中,扩展方法必须是静态的 public static class TestExtension { public static void ActionExtension(this Test t) //第一个参数必须是要扩展的类型,且必须加上了this关键字 { }
public static void ActionExtension1(this Test t, int a) { }
}
//这个时候就可以调用拓展方法了
Test t = new Test();
t.ActionExtension();
t.ActionExtension1(0);
注意:不支持扩展事件和属性,但是可以扩展接口
避免双向耦合
双向耦合指两个类型之间互相引用.一般来说,类型之间不应该存在双向耦合,如果出现,则考虑重构。