程序员要朝“内”和向“外”两个方面扩展自己的知识和技能:
内 —— 指的是编写代码的基本功、数据结构思想、设计模式等。
“修内”四要素:
1. 深刻理解面向对象编程思想;
2. 精通C#编程语言特点;
3. 熟悉设计模式的23种模式,理解各个模式UML图
4. 了解软件工程过程,掌握数据结构的概念和技术;
外 —— 指的是新技术的热情、知识的广度、注重扩展性等。
“修外”五要素:
1. 对新技术的理解和远见;
2. 通过项目的实践熟悉 DB 设计、SQL Server 或 Oracle 技术;
3. 清晰理解代码实现方式、范例、以及.NET相关接口;
4. 理解 Web 2.0 理念、Blog/Wiki/RSS 架构、SOA 理念、软件测试,了解网络和其它操作系统;
5. 知道如何面对英语面试;
(P15) 工资 —— 一定要问清楚是税前还是税后,这点不用多说。另外,还要问清楚,发多少个月。很多单位有年底双薪,还有一些单位会发14-16个月不等。
(P15)
“五险一金” —— 养老保险、医疗保险、失业保险、人身意外伤害保险、生育保险。“一金”指的是住房公积金。
有的单位公积金比例上得非常高,所以你工资扣得也很多,那意味着公司交的钱更多,而一旦买房时,这些钱都是你自己的。所以,这部分收入不能忽视。
有些单位还会向你提供补充医疗保险、补充养老保险、补充意外保险、住房无息贷款或经济适用房等,也要问清楚。
(P16) 关于加班,国家有规定:如果周六、周日加班的话,可以获得正常工资2倍的加班费;如果是五一、十一这样法定的假日加班的话,可以获得正常工资3倍的加班费。
(P29) 事情都是人做出来的,关键是人。
(P30) 正确的做法是和那些比你强的人打交道,看他们是怎么想的、怎么做的,学习他们,然后最终提升自己的能力才是最重要的。
(P35) 语言有“无类型”、“弱类型”和“强类型”3种:
1. “无类型” —— 不检查,甚至不区分指令和数据;
2. “弱类型” —— 检查很弱,仅能严格地分指令和数据;
3. “强类型” —— 严格地在编译期进行检查;
(P36) GAC —— Global Assembly Cache (全局应用程序集缓存),它解决了几个程序共享某一个程序集的问题。
(P37)
值类型的实例通常是在线程栈上分配的(静态分配),但是在某些情形下可以存储在堆中。
引用类型的对象总是在进程堆中分配(动态分配)。
引用类型和值类型都继承自 System.Object 类,不同的是,几乎所有的引用类型都直接从 System.Object 继承,而值类型则继承其子类,即直接继承 System.ValueType 。
(P38) 所有的值类型都是密封的,所以无法派生出新的值类型。
(P39) 引用类型可以包含 Null 值, 值类型不能。
(P40)
引用类型在栈中存储一个引用,其实际的存储位置位于托管堆。
值类型(不支持多态)适合存储C#应用程序的数据,而引用类型(支持多态)应该用于定义应用程序的行为。
(P43) 装箱就是将值类型转换为引用类型的过程,并从栈中搬到堆中。而拆箱就是把引用类型转换为值类型。
(P45) DateTime 为 Struct 类型。
(P47)
关键字 const (静态常量):
1. 在编译期间解析的常量;
2. 必须在声明同时就初始化;
3. 既可用来修饰类中的成员,也可修饰函数体内的局部变量;
关键字 static readonly (静态常量):
1. 在运行期间解析的常量;
2. 既可以在声明时初始化,也可以在构造器中初始化;
3. 只可以用于修饰类中的成员;
(P51)
问: 定制的异常类应该继承哪个类? 应包含哪些构造函数?
答: 定制的异常类应从 Application.Exception 派生。按照约定,异常名应以 Exception 结尾, 应包含 Exception 基类定义的3个公共构造函数:
1. 默认的无参构造函数;
2. 带一个字符串参数(通常是消息)的构造函数;
3. 带一个字符串参数和一个 Exception 对象参数的构造函数;
(P60)
“==”判断符号左右两个 Object 是否指向统一内存地址;
“Equals()”判断两个 Object 是否一样 (所有成员值一样);
(P63)
在.NET Framework 中,由3种序列化机制:二进制、XML和简单地向访问协议(SOAP),它们的优缺点如下:
1. 二进制序列化的最大优点是: 类型数据可以准确地表示出来。因为二进制序列化对象的公有和私有成员,所以在反序列化的时候可以忠诚地重建出该对象的状态;
2. XML 只序列化对象的公有属性和字段。在 XML 序列化时,私有字段和其它实例化对象就失去了;
3. XML 和 SOAP 是开放标准,具有很好的移植性;
(P72) Random r = new Random(unchekced(int)DateTime.Now.Ticks));
(P73)
过程式编程语言为: 程序 = 算法 + 数据;
面向对象编程语言为: 程序 = 对象 + 消息;
(P76) 抽象类或者包含私有构造函数的类都不能实例化。
(P79) internal protected 的语意应该是 “internal || protected”
(P80) 栈的访问速度比堆要快,但栈的资源有限。
(P88) 虚函数的目的就在于实现多态性。
(P92) 如果没有写静态构造函数,而类中包含带有初始值设定的静态成员,那么编译器会自动生成默认的静态构造函数。
(P95)
“覆盖 (Override)” —— 指子类重新定义父类的虚函数的做法;
“重载 (Overload)” —— 指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同);
重载只是一种语言特性,与多态无关,与面向对象也无关;
封装可以隐藏实现细节,使得代码模块化;
继承可以扩展已存在的代码模块(类);
它们的目的都是为了 —— 代码重用
多态是为了实现另一个目的 —— 接口重用;
“接口是公司最有价值的资源。设计接口比用一堆类来实现这个接口更费时间,而且接口需要耗费更昂贵的人力的时间”。
继承的为重用代码而存在的理由已经越来越薄弱,因为“组合”可以很好地取代继承的扩展现有的代码的功能,而且“组合”的表现更好(至少可以防止“类爆炸”)。继承的存在很大程度上是作为“多态”的基础,而非扩展现有代码的方式。
(P99)
接口:
—— 从广义上说,凡是一个类提供给外部使用的部分都可以被称为接口。广义接口的真正意义是在类的继承中体现多态的功能,这种接口又被称为抽象类接口。
—— 从狭义上说,接口是指特定的函数集合,一般是用 Interface 声明的,它表示一个方法集合,这个集合被称为一个命名接口。
从上述认识来看,接口实际上是结合着多态而来的,它的最大的任务就是实现多态,而多态又是面向对象最精华的理论。掌握了多态,也就掌握了面向对象的精髓。但掌握多态必须先理解和掌握接口,只有充分理解接口的定义,才能更好地应用多态。
(P104)
在C#中,new 关键字可用作运算符、修饰符或约束。
new 修饰符和 override 修饰符不可同时用在一个成员上,因为这两个修饰符在含义上相互排斥。
(P108) 如果想调用子类的 new 方法,用子类的句柄(绝对不能用基类句柄)来调用。
(P110) 在构造函数中,通过 this 可以调用同一 class 中别的构造函数。
(P112)
子类被构造时一定会先调用父类的构造函数,但可以用 base 关键字选择调用哪个构造函数。
决定调用哪一个,但不能哪个都不调用(至少选一个)。如果不指定的话,一般会调用无参数的构造函数,因为这是一个类的默认的构造函数。
(P113) 抽象类允许包含抽象成员,但这不是必需的(可以允许一个抽象类中没有任何抽象成员),抽象类中可以有非抽象方法。
(P116) 接口中的接口成员可以是方法、属性、事件和索引器。
(P188) abstract 修饰符不可以和 static、virtual 和 sealed 修饰符一起使用,但是可以和 override 修饰符一起使用。
(P123) 显式为接口的方法指定 public 修饰符是非法的。
(P127) 委托在编译的时候确定会编译成类。
(P128) 委托是一个类,它定义了方法的类型,使得可以将方法当做另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,使得程序具有更好的可扩展性。
(P131) 声明一个事件类似于声明一个进行了封装的委托类型的变量。
(P145)
1. NLR : 前序遍历 (Preorder Traversal) —— 访问结点的操作发生在遍历其左右子树之前,即根左右;
2. LNR : 中序遍历 (Inorder Traversal) —— 访问结点的操作发生在遍历其左右子树之间,即左根右;
3. LRN : 后序遍历 (Postorder Traversal) —— 访问结点的操作发生在遍历其左右子树之后,即左右根;
(P146)
“满二叉树” —— 对于所有结点都达到最大的二叉树;
“完全二叉树” —— 叶子结点仅在层次最大的两层出现,对于任意一结点,左子树高度只等于右子树高度或者右子树高度加一;
(P153) System.Text.Encoding.Default.GetBytes(strTmp).Length —— 里面的 Default 属性,在默认情况下,英文字母用一个字节表示,汉字用双字节表示。
(P160)
在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的;若具有相同关键字的记录之间的相对次序发生变化,则这种排序方法是不稳定的。
稳定的排序 ——
排序名称: 气泡排序 (Bubble Sort)
时间复杂度: 最差、平均都是 O(n2);最好是 O(n)
空间复杂度: 1
排序名称: 鸡尾酒排序 (Cocktail Sort) (双向的冒泡排序)
时间复杂度: 最差、平均都是 O(n2);最好是 O(n)
空间复杂度: 1
排序名称: 插入排序 (Insertion Sort)
时间复杂度: 最差、平均都是 O(n2); 最好是 O(n)
空间复杂度:1
排序名称: 归并排序 (Merge Sort)
时间复杂度: 最差、平均、最好都是 O(nlogn)
空间复杂度: O(n)
排序名称: 桶排序 (Bucket Sort)
时间复杂度: 最差、平均、最好都是 O(n)
空间复杂度: O(k)
排序名称: 基数排序 (Radix Sort)
时间复杂度: 最差、平均、最好都是 O(dn) (d是常数)
空间复杂度: O(n)
排序名称: 二叉树排序 (Binary Tree Sort)
时间复杂度: 最差、平均、最好都是 O(nlogn)
空间复杂度: O(n)
排序名称: 图书馆排序 (Library Sort)
时间复杂度: 最差、平均、最好都是 O(nlogn)
空间复杂度: (L+&)n
不稳定的排序 ——
排序名称: 选择排序 (Selection Sort)
时间复杂度: 最差、平均都是 O(n2)
空间复杂度: 1
排序名称: 希尔排序 (Shell Sort)
时间复杂度: 最差、平均、最好都是 O(nlogn)
空间复杂度: 1
排序名称: 堆排序 (Heap Sort)
时间复杂度: 最差、平均、最好都是 O(nlogn)
空间复杂度: 1
排序名称: 快速排序 (Quick Sort)
时间复杂度: 平均是 O(nlogn); 最坏的情况下是 O(n2)
空间复杂度: O(logn)
(P165)
应用交换排序基本思想的主要排序方法有: 冒泡排序和快速排序。
(P183) 作为设计者,应该拥抱变化、利用变化,而不是逃避变化。
(P192)
MVC (Model / View / Controller) 模式是一种使用的较多的设计模式。 MVC 包括了类对象: Model 是应用对象;View是它在屏幕上的表示; Controller 定义用户见面对用户输入的响应方式。
1. 模型 (Model):是应用程序的主体部分,模型表示业务数据,或者业务逻辑;
2. 视图 (View): 是应用程序中用户界面相关的部分,是用户看到并与之交互的界面;
3. 控制器 (Controller):工作就是根据用户输入控制用户界面数据显示和更新 Model 对象的状态;
(P201)
类与类之间存在以下关系:
1. 泛化 (Generalization)
2. 关联 (Association)
3. 依赖 (Dependency)
4. 聚合 (Aggregation)
泛化 —— 指类与类之间的继承关系、接口与接口之间的继承关系或类对接口的实现关系;
依赖 —— 指对两个相对独立的对象,当一个对象负责构成另一个对象的实例,或者依赖另一个度喜爱那个的服务时,这两个对象之间主要体现为依赖关系;
关联 —— 指对于两个相对独立对象,当一个对象的实例与另一个对象的一些特定实例存在固定的对应关系时,这两个对象之间为关联关系;
聚合 —— 指当对象 A 被加入到对象 B 中,成为对象 B 的组成部分时,对象 B 和 对象 A 之间为聚合关系;
聚合是关联关系的一种,是较强的关联关系,强调的是整体与部分之间的关系;
关联与聚合的区别:
1.
关联关系所涉及的两个对象是处在同一个层次上的;
聚合关系所涉及的两个对象是处于不平等的层次上,一个代表整体、一个代表部分;
2. 对于具有聚合关系的两个对象,整体对象会制约它的组成对象的生命周期。部分类的对象不能单独存在,它的生命周期依赖于整体类的对象的生命周期,当整体消失,部分也就随之消失;
(P222)
一个进程至少包含一个线程;
当一个程序开始运行时,它就是一个进程。进程包括运行中的程序和程序所使用到的内存和系统资源;
(P227)
作业调度算法:
1. 先来先服务;
2. 轮转法;
3. 多级反馈队列算法;
4. 优先级法;
5. 最短作业优先法;
6. 最高响应比优先法;
进程调度算法:
1. 先进先出算法;
2. 最短 CPU 运行期优先调度算法;
3. 轮转法;
4. 多级反馈队列;
(P228)
“sleep()” —— 是使线程停止一段时间的方法。在 sleep 时间间隔期满后,线程不一定立即恢复运行。
“wait()” —— 是线程交互时,如果线程对一个同步对象 X 发出一个 wait 的调用,该线程会暂停执行,被调用对象进入等待状态,知道被唤醒或等待时间到。
(P238)
“存储过程” —— 是用户定义的一系列 SQL 语句的集合,涉及特定表或其它对象的任务,用户可以调用存储过程;
“函数” —— 通常是数据库已定义的方法,它接受参数并返回某种类型的值,并且不涉及特定用户表;
“事务” —— 作为一个逻辑单元执行的一系列操作,一个逻辑工作单元必须有4个属性,成为 ACID (原子性、一致性、隔离性和持久性) 属性, 只有这样才能成为一个事务;
(P275)
“单项绑定” —— <%# Eval("username") %>
“双向绑定” —— <%# Bind("title") %>
(P276) 在数据绑定控件的 EditItemTemplate 或 InsertItemTemplate 中要使用 Bind 函数。
(P278)
ASP.NET 页面在触发各个子控件的事件之后,会递归调用控件的 OnPreRender , 然后递归地将控件的 ViewState 序列化成一个字符串,最后递归调用控件的 Render 输出结果。
在 DataBind 的事件中,ItemCreated 和 ItemDataBind 是尤为重要并且经常要用到的两个事件。
ItemCreated 事件在 DataGrid 创建表格时触发。
ItemDataBound 事件在数据绑定到相应的行后触发。
(P283) Session 在服务器和客户端各保留一个副本,关闭浏览器与否与 Session 是否存在没有任何关系。
(P284) Session 机制可能需要借助于 Cookie 机制来达到保存表示的目的,但实际上还有其它选择。
(P285)
“Application” —— 是公共的,所有人都能看到;
“Session” —— 是私有的,每个客户端都存在一个不同的 Session 生存期;
“Cookie” —— 是保存在本机的文件,记录短小的信息,除非 Cookie 过期,否则会一直存在;
“ViewState” —— 类似于 ASP 中的 Hidden 控件,用来记录页面中控件的状态,主要在页面间传递信息时用;
“Cache” —— 是缓存,用来记录已经执行过的一些数据,比如读取数据库目的是加速显示,减少服务器的负担,过期时间也是可以自己设定的;
(P288) XML 注释 : <!-- -->
(P288)
ASP.NET页面之间传递参数:
1. URL 链接地址传递 —— QueryString
2. Post 方式 —— Request.Form["***"]
3. Session 传递
4. Application 传递
5. Server.Transfer 传递
(P290)
GET 请求:
1. 利用一个问号“?”代表 URL 地址的结尾数据参数的开端;
2. 后面的参数每一个数据参数以 “名称 = 值”的形式出现;
3. 参数与参数之间利用一个连接符“&”来区分;
(P291)
防盗链:
1. 检查Refer;
2. 为资源文件添加数据签名;
3. Session验证;
(P288) XML Web Service 与 .NET Remoting
1.
名称: XML Web Service
容易操作: 容易
跨平台: 是
充分利用 .NET Framework 功能:不充分
精确传递数据格式: 不精确
支持状态: Stateless
对象作业模式: 无
支持通信协议: HTTP
执行效率: 低
2.
名称: .NET Remoting
容易操作: 较难
跨平台: 否
充分利用 .NET Framework 功能:充分
精确传递数据格式: 精确
支持状态: Stateful 或 Stateless
对象作业模式: 丰富(单次呼叫、单一对象、前端启用)
支持通信协议: HTTP、TCP(可扩充)
执行效率: 高
(P304)
“Finalize()” —— 用于隐式释放资源;
“Dispose()” —— 用于显式释放资源;
(P311) 在面试面前,面试者应对应聘公司有所了解。比如公司的规模、业务、未来发展等。对公司文化理解是否深刻,是你超出其他应聘者的一个亮点。
(P366)
知识是用来用的,不是用来当摆饰唬人的。