1 ArrayList 一旦这块内存被填满,它就分配一块更大的连续内存(通常是原先的两倍大),会把既有的元素复制到新的空间去。
如果插入完元素,可以考虑使用:text.TrimToSize(),调整容量,使它刚好吻合实际的元素数量。
2 如果元素不超过10个,Idictionary 以单向链表完成,它比Hashtable还要快
3 Hashtable将value存储为object型别:涉及转型(拆箱)
4 前缀字符'@'在与其他语言进行接口整合(interfacing)时很有用,更明确地说是在某个c#关键字被其他语言视为标识符时很有用。‘@’字符并非标识符的一部分,只是提供一个“将此关键字视为标识符”的脉络背景。
5 函数最好只执行单一任务。
6 在c#领域,出现错误后的通常做法是抛出异,而不是返回一个表示错误的状态码(例如HRESULT).
7 缺省情况下,如果某个成员函数(或class的数据成员)未明白带有访问级别,便视为private级别。
8 一步一步地在一个能够动作的程序上累加功能,比一口气编写一大堆代码而不知道它们是否可执行,生产力高得多。
9 “信息隐藏”解决了紧耦合的难题,却又提出了另一道问题:如何让用户读写某个private的数据成员?c#的解决之道是在某个具名的(named) class property内提供"get" 和 "set"访问器(accessors).
10 class的所有数据成员都会自动初始化为其型别的缺省值。数值型别(Numeric types)如int 和 double的缺省值为0. bool的缺省初值是false。所有reference的型别的缺省初值是null。缺省初始化动作(default initialization)是operator new 被调用时自动执行起来的一部分动作。
11 构造函数是一种特殊的class成员函数,它与class同名,而且不能返回任何值,也不能声明返回型别(return type) ---即便声明为void也不行。
12 static构造函数仅在“此class的某个实体被创建”或"此class的某个static成员被取用"的条件下,才会被调用(而且只被调用一次).
13 static成员函数由于缺少this reference,因此不能被直被访问它所属的class的任何instance成员。
14 const 成员本质上就是一种只读的(read-only)static成员:访问时必须使用class 名称,而非object名称。
15 缺省情况下,第一个枚举元被赋值为0。其后每个枚举元的值自动增加1.
16 delegate obj 可以同时代表(指向)多个成员函数。
17 好消息是,我们不必担心delegate object所代表的成员函数所属的object会失效。直到delegate object不再代表那个成员函数,此object才会被垃圾回收。也不必担心object在我们不注意时突然消失了。
(boost::function还是有这个问题)坏消息是,此object会持续存在,直到delegate object不再引用该object的成员函数。
18 对ref参数和out参数而言,引数型别必须完全匹配(不考虑转换)。
19 最容易达到的转换,就是首选转换。
20 关键字params 用以指明“参数个数不定”。
21 c#提供一种机制,让每个class都可以定义一组"可应用于其object身上"的隐式(implicit)转换或显示(explicit)转换。
22 c#支持非确定性的析构函数(nondeterministic destructor method),但并不鼓励使用。析构函数的非确定性表现在两方面.第一,我们无法预知析构函数何时被调用,甚至无法预知它是否会被调用。 第二,我们无法预知析构函数被调用的顺序。从性能角度看,“带有析构函数”的classes在与垃圾回收器(garbage collector)打交道时会背负沉重的额外开销。
23 习惯上我们把资源归还动作安排在Dispose()之中,这个成员函数必须由用户手工调用。
24 struct object初始化另一个struct object时,或是将一个struct object赋值给另一个struct object时,发生的是深拷贝(deep copy),意味着两个objects持有相同的值,但仍旧保持独立。这一点和reference型别的"浅拷贝语义"(shallow-copy semantis)不同。
25 面对struct,除了"不得为它引入default构造函数外",另外还有两个限制:(1)其数据成员的声明式不得包含初始化动作. (2) 不得为struct提供构函数。
26 如果要让某个成员函数通过动态绑定来进行决议,也就是在运行期依照调用者(某个object)的实际型别来决议,我们必须将函数明白标上关键字virtual,否则函数会被视为non-virtual.
27 static成员函数并不支持动态绑定,原因是你不能通过class object调用static成员函数。
28 如果base-class的某个成员函数不具备带有意义的缺省实现,我们就应该把这样的成员函数声明为abstract,并且不为它写出函数体。
29 就初始化而言,运行derived-class的构造函数之前,相应的base-class构造函数会自动施行于subobject之上。
30 如果想要覆写继承而来的abstract或virtual成员,我们必须在定义式前标上关键字override,否则编译器会将这一实现体视为独立定义,只不过是重用(reuse)了继承而得的成员名称罢了。
31 string object是不可变的(immutable),每次改动string,其实都会导致产生新的string object。
32 StringBuilder则是可变的(mutable),这使我们得以生成一个string而不产生多个临时实体。完成对字符串的修改后,我们再以StringBuilder的ToString()从StringBuilder object中取出字符串来。
33 如果明确地防止从某个class派生新的class,可以指定关键字sealed:
sealed public class BinaryTree{...}
34 关键字sealed不能用于struct,因为后者已被陷式声明为sealed;亦不能用于abstract class,因为后者要求其继承下去的classes必须提供具体实现。
35 通过sealed class object而调用的虚函数可以在编译期被静态决议。这时候不仅不需要虚拟机制,还有机会做内联展开(inline expansion,一种编译器优化行为),可以显著提高被频繁运用(像是string和collection classes)时的性能。
36 当某个抽象性(abstraction)需要最理想的性能(效率),但又适合作为value型别时,那么sealed class是可供选择的另一种设计。
37 Interface的所有成员者暗自(implicitly)成为abstract.我们不能为它提供缺省实现。
38 C#的arra索引从0开始,也就是说第一个元素的索引(下标)是0.
39 IEnumerator 的正确用法是,在第一次了以用Current之前先调用MoveNext().如果下一个元素能被取用,MoveNext()就返回true。
40 Array.IndexOf()所用的查找算法的复杂度是线性的,也就是说,它会依次检视array中的每个元素,直到发现查找目标,或者直到所有元素都检视完毕。对于大型Array,二分查找法(binary search)效率更高但它要求array必须先排序。