[C#高级编程]基础知识摘要一
核心C#:
值类型存储在堆栈中,而引用类型存储在托管堆上。
object类型可以用于两个目的:
可以使用object引用绑定任何子类型的对象
object类型执行许多一般用途的基本方法,包括Equals(), GetHashCode(), GetType()和ToString().
在C#中,switch语句的case子句的排放顺序是无关紧要的,甚至可以把default子句放在最前面,因此,任何两条case都不能相同,这包括值相同的不同常量。
foreach循环不能改变集合中各项的值.
Goto语句的限制:不能跳转到像for循环这样的代码块中,也不能跳出类的范围,不能退出try…catch块后面的finally块。
break用于退出判断(switch语句)或者循环(for, foreach, while等)语句,该语句会使控制流执行循环后面的语句。
continue语句也必须在循环中使用,但它只退出循环的当前迭代,开始执行循环的下一次迭代,而不是退出循环。
对象和类型:
结构和类的区别是它们在内存中的存储方式、访问方式(类是存储在堆上的引用类型,而结构是存储在栈上的值类型)和它们的一些特征(如结构不支持继承)。
参数可以是可选的,必须为可选参数提供默认值,且可选参数必须是方法定义的最后一个参数。
无参数的实例构造函数与静态构造函数可以在同一个类中同时定义,尽管参数列表相同,但这并不矛盾,因为在加载类时执行静态构造函数,而在创建实例时执行实例构造函数,所以何时执行哪个构造函数不会有冲突。
readonly关键字比const灵活得多,允许把一个字段设置为常量,但还需要执行一些计算,以确定它的初始值。其规则是可以在构造函数中给只读字段赋值,但不能在其他地方赋值。只读字段还可以是一个实例字段,而不是静态字段,类的每个实例可以有不同的值。
在构造函数中不必给只读字段赋值,如果没有赋值,它的值就是其特定数据类型的默认值,或者在声明时给它初始化的值。这适用于只读的静态字段和实例字段。
扩展方法允许改变一个类,但不需要该类的源代码。它是静态方法,是类的一部分,但实际上没有放在类的源代码中。对于扩展方法,第一个参数是要扩展的类型,放在this关键字后面。可以访问扩展类型的所有公有方法和属性。
继承:
实现继承:表示一个类型派生于一个基类型,拥有该基类的所有成员字段和函数。在实现继承中,派生类型采用基类型的每个函数的实现代码,除非在派生类型的定义中指定重写某个函数的实现代码。在需要给现有的类型添加功能,或许多相关的类型共享一组重要的公共功能时,这种类型的继承非常有用。
接口继承:表示一个类型只继承了函数的签名,没有继承任何实现代码。在需要指定该类型具有某些可用的特性时,最好使用这种类型的继承。
结构总是派生自System.ValueType, 它们还可以派生自任意多个接口
类总是派生自用户选择的另一个类,它们还可以派生自任意多个接口
把一个基类函数声明为virtual,就可以在任何派生类中重写该函数,也可以把属性声明为virtual,对于虚属性或重写属性,语法与非虚属性相同,但要在定义中添加关键字virtual:
1 class MyBaseClass 2 { 3 public virtual string VirtualMethod() 4 { 5 return "This method is virtual and defined in MyBaseClass"; 6 } 7 } 8
在派生类的函数重写另一个函数时,要使用override关键字显示声明:
1 class MyDerivedClass: MyBaseClass 2 { 3 public override string VirtualMethod() 4 { 5 return " This method is an override defined in MyDerivedClass"; 6 } 7 }
成员字段和静态函数都不能声明为virtual
如果签名相同的方法在基类和派生类中都进行了声明,但该方法没有分别声明为virtual 和 override,派生类方法会隐藏基类方法
可以使用base.<MethodName>()语法调用基类中的任何方法,不必从同一个方法的重载中调用它
抽象类不能实例化,抽象函数不能直接实现,必须在非抽象的派生类中重写
如果类包含抽象函数,则该类也是抽象的,也必须声明为抽象的:
1 abstract class Building 2 { 3 public abstract decimal calculateHeatingCost(); 4 }
要在方法或属性上使用sealed关键字,必须先从基类上把它声明为要重写的方法或属性。如果基类上不希望有重写的方法或属性,就不要把它声明为virtual
构造函数的调用顺序是先调用System.Object,再按照层次结构由上向下进行,直到到达编译器要实例化的类为止。每个构造函数都初始化它自己的类中的字段。
base和this关键字是调用另一个构造函数时允许使用的唯一关键字,其他关键字都会产生编译错误。
接口仅表示其成员的存在性,类负责确定这些成员是虚拟还是抽象的。
接口引用的强大之处在于,它可以引用任何实现该接口的类。