类
类是引用类型,因此类对象的变量引用该对象在托管堆上的地址,声明为引用类型的变量缺省值为null。
结构体
(C#中叫结构,但是本人母语是C++,习惯叫结构体了)
结构体是值类型,结构体对象的变量具有整个对象的副本。结构体的实例也可以通过new创建,但不是必须的。不使用 new 时将不会调用任何构造函数,提高了分配效率,但是字段也将保持默认值状态。
- 在结构体声明中,除非将字段声明为 const 或 static ,否则无法初始化,字段将保持默认值状态。
- 结构体不能声明默认构造函数。但是可以声明具有参数的构造函数,此时必须显式初始化所有成员,否则会生成编译器错误。
- 结构体可以实现接口。
两个对象是否相等
- 若要确定两个类实例是否引用内存中同一位置,可以使用 System.Object的静态方法 Equals 。
- 若要确定两个结构体实例中的字段是否具有相同的值,可使用 System.ValueType.Equals 方法。(System.ValueType的Equals的实现使用了反射机制,因为它需要确定结构体中有哪些字段,重写Equals方法可以提供特定于你的类型的高效求等算法)
继承
- 派生类只能有一个直接基类
多态性
多态是自封装和继承之后,面向对象编程的第三个支柱。
多态性有两个截然不同的方面:
- 基类可以定义并实现虚方法(virtual),派生类可以重写(override)这些方法,提供自己的实现。
- 在运行时在方法参数,集合或数组等位置,派生类的对象可以作为基类的对象处理。
- (凭以前学习C++的印象,函数重载也是多态的一种体现)
在C#中,派生类可以包含于基类方法同名的方法。
- 基类方法必须定义为virtual
- 若派生类的方法前带有 override 关键字,则派生类的对象将调用改方法,而不是调用基类方法
- 若派生类方法前带有 new 关键字,则改方法被定义为独立于基类中的方法
- 可以在派生类中使用 base 关键字调用基类方法
- virtual,override,new 关键字还可用于属性,索引器和事件中
抽象类,密封类及成员
- 使用 abstract 关键字可以创建不完整且必须在派生类中实现被标记为 abstract 的方法的抽象类。
- 抽象类不能被实例化
- 抽象方法没有实现,所以方法定义后面是分号而不是方块
- 包含抽象方法的类必须声明为抽象类
- 类定义前放置 sealed 关键字可以将类声明为密封类
- 密封类不被派生
- 可以在派生类对基类的重写函数 override 前放置 sealed 关键字,禁止后续派生类重写
静态类和静态成员
- 静态类只包含静态成员。
- 静态类无法实例化。
- 更典型的做法是,声明具有一些静态成员的非静态类,而不是将整个类声明为静态类。
成员
- 属性(Properties),属性可以为字段提供保护,避免被随意修改
- 运算符(Operators),重载运算符被视为类成员,将运算符定义为公有静态方法。预定义运算符(+,*,<等)不被视为成员。
访问修饰符
- internal :同一程序集中都可以访问。
- protected internal : 在对其声明的程序集内,或另一个程序集的派生类中可访问。
- private protected : 在对其声明的程序集内,同类或派生类可访问。
- 默认情况下,类和结构体的访问修饰符为 internal,内部成员的访问级别为 private。
常量
- 仅C#内置类型(不含System.Object)可以声明为 const,用户定义的类型(类,结构,数组)不能为 const
属性
class Person
{
private string name; // name字段
public string Name // Name属性
{
get
{
return name;
}
set
{
if(value.Length > 0) name = value;
}
}
}
属性不会被归类为变量,因此不能将属性作为 ref 或 out 参数传递。
属性具有的用途:
- 可以先验证数据,再允许更改
- 可以在类上公开数据,其中数据是从其他源(如数据库)检索到的
- 可以在数据发生更改时采取措施,例如引发事件或更改其他字段的值
接口(interface)属性的访问器没有正文。因此访问器的用途是指示读写开放性。
传递值类型参数
- 按值传递值类型:方法内发生的改变不会影响该变量的原始值。(传递值的副本)
- 按引用传递值类型:使用 ref 关键字修饰参数,方法中所作的任何更改都会影响原始变量。(传递引用)
传递引用类型参数
- 按值传递引用类型:方法内对对象的成员数据的修改会影响原始对象的成员数据,但是对对象本身引用的修改不会影响原始对象。(传递引用的副本)
- 按引用传递引用类型:使用 ref 关键字修饰参数,方法中所作的任何更改都会影响原始变量。(传递引用)
向方法传递结构体与类的区别
若参数不加 ref 关键字修饰,则按照值传递方式,注意!结构体是值类型,类是引用类型,所以此时结构体属于“按值传递值类型”,类属于“按值传递引用类型”。结果是
- 方法内对结构体的任何修改不会影响原始变量
- 方法内对类实例成员的修改会影响原始实例的成员,对实例本身的修改不会影响原始实例的地址。
扩展方法
扩展方法可以使你无需修改原始类型或创建派生类来向现有类型添加方法。扩展方法被定义为静态方法,但是可以通过实例方法语法调用。
最常见的扩展方法是LINQ(标准查询运算符)。多数时候我们只是调用扩展方法而非实现自己的扩展方法。扩展方法的优先级总是比类型本身定义的实例方法低。MSDN建议,能通过派生类来达到目的就不要使用扩展方法。
可选参数
调用方可以不为参数列表的可选参数传值
public void ExampleMethod(int required, string optionalstr = "default string")
私有构造函数
私有构造函数可用于阻止外部创建该类的实例。声明空构造函数可阻止自动生成默认构造函数。
静态构造函数
静态构造函数可用于初始化静态数据,或仅需执行一次的特定操作。静态构造函数的触发时机:
- 创建第一个实例之前
- 引用任何静态成员之前
终结器(析构函数)
终结器被自动调用,终结器会隐式调用基类的 Finalize 方法。
分部类和方法
拆分一个类,结构体,接口或一个方法的定义到多个文件中,每个源文件包含类型或方法的一部分定义,编译时这些部分会被组合起来。若要拆分类的定义,使用 partial 关键字修饰。
网友评论