什么是面向对象
面向对象三大特性
封装,把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
继承,它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
多态,指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。
面向对象五大原则
单一职责原则,一个类应该只有一个引起他变化的原因。
开放封闭原则,对扩展是开放的,对更改是封闭的。
里氏替换原则,子类可以替换父类并且出现在父类能够出现的任何地方。
依赖倒置原则,传统的结构化编程中,最上层的模块通常都要依赖下面的子模块来实现,也称为高层依赖低层。所以依赖倒置原则就是要逆转这种依赖关系,让高层模块不要依赖低层模块。
接口隔离原则,使用多个专门的接口比使用单个接口要好的多。
C#常用容器及其数据结构
Array,属于System.Array命名空间,数组,在内存中是连续存储的。
ArrayList,属于System.Collections,不需要指定长度能动态扩容。所插入的数据为object类型,会发生装箱拆箱。类型不安全。
List<T>,属于System.Collections.Generic,底层数据结构是数组,避免了装箱拆箱,并且类型安全。
LinkedList<T>,属于System.Collections.Generic,底层数据结构是双向链表,类型安全,因为是链表实现的索引不用动态扩容
HashSet<T>,属于System.Collections.Generic,底层数据结构是哈希表,不能用索引访问,值不能重复且没有顺序。
HashTable,属于System.Collections,底层数据结构是哈希表,键值对均为object类型,发生装箱拆箱,key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。
Dictionary<T>,属于System.Collections.Generic,底层数据结构是哈希表,因为是泛型所以没有装箱拆箱。
总结,C#所有泛型容器都在System.Collections.Generic命名空间下,非泛型容器在System.Collections空间下。
结构体和类的区别
内存中的差别,类的实例一定在堆上,结构体的实例一般在线程栈上分配(虽然也可以作为字段嵌入引用类型的对象中)。类的变量是实例在堆中的内存地址,结构体的变量中包含了实例本身的字段。这也是值类型和引用类型的区别。
字段的差别,结构体中不能设置字段默认值,类可以。
默认构造器的差别,结构体和类都有默认的实例构造器,但结构体不能显式给出。
自定义构造器的差别,自定义的构造器,类定义了后默认的被隐藏,无参构造器就需要自己给出,不需要把所有字段初始化,结构体必须初始化所有实例字段和未初始化的非静态的字段。
声明实例时的差别,结构体在声明的时候就已经为其分配栈上的内存了,new只是初始化其字段,而类需要用new为其分配堆上面的内存。
可访问性的差别,所有值类型都隐式密封,目的是防止将值类型用作其他引用类型或值类型的基类型。
重载和重写的区别
重载是对于同一类中的方法来讲:有相同的方法名,相同的返回值,只是参数不同
重写是对继承来说,子类可以重写父类中的方法。要求方法名,返回值,参数都必须相同。
foreach的实现
能使用foreach的集合需要实现什么
首先该集合要实现IEnumerable接口,该接口只有一个IEnumerator GetEnumerator方法,在该方法里返回一个实现了IEnumerator接口的类型的对象,该类型实现了IEnumerator接口以及其中的object Current属性,bool MoveNext方法,void Reset方法,在类中实现了遍历一个数组。该类型对象就会返回给集合的GetEnumerator方法。实现了这样方法的集合就可以使用foreach的语法来遍历了。
foreach语句本质是如何获取集合中元素的
将foreach语句翻译成代码就是声明一个IEnumerator接口类型的变量enumerator,调用集合的GetEnumerator方法返回值赋值给变量enumerator,然后使用while循环enumerator.MoveNext方法直到方法返回false即数组元素遍历结束,在循环中获取enumerator.Current即对应的数组成员。
private、protected、public、internal之间的区别
private是私有的,只有类自身成员可访问。
protected是受保护的,只有类自身和派生类可访问。
public是公有的,任何类和成员都可访问。
internal是内部的,只有同一程序集内可访问。
接口和抽象类的区别
抽象类中可以有构造方法,接口不能有。
抽象类中可以有普通成员变量,接口不能有。
抽象类中可以包含非抽象的普通方法,接口不能有。
抽象类中可以有静态方法,接口不能有。
抽象类中抽象方法访问类型可以是public或protected类型的,但接口默认是public和abstract类型的。
抽象类中静态成员的可访问性是任意的,接口中的默认只能是public static final类型。
一个类可是实现多个接口,但只能继承一个抽象类。
抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的。