学习<你必须知道的.net>感想
首先谢谢王涛愿意分享他的知识。 令人受益很多。 有些东西还是记下来的好,免的到时又忘了。
一 NEW的作用,
1
- 作为运算符, 用于创建对象和调用构造函数。
本文的重点内容,本文在下一节来重点考虑。
- 作为修饰符,用于向基类成员隐藏继承成员。
作为修饰符,基本的规则可以总结为:实现派生类中隐藏方法,则基类方法必须定义为virtual;new作为修饰符,实现隐藏基类成员时,不可和override共存,原因是这两者语义相斥:new用于实现创建一个新成员,同时隐藏基类的同名成员;而override用于实现对基类成员的扩展。
另外,如果在子类中隐藏了基类的数据成员,那么对基类原数据成员的访问,可以通过base修饰符来完成。
2
- 作为约束,用于在泛型声明中约束可能用作类型参数的参数的类型。
MSDN中的定义是:new 约束指定泛型类声明中的任何类型参数都必须有公共的无参数构造函数。当泛型类创建类型的新实例时,将此约束应用于类型参数。
注意:new作为约束和其他约束共存时,必须在最后指定。
其定义方式为:
{
public T GetItem()
{
return new T();
}
}
class MyGenericTester
{
public static void Main(string[] args)
{
Genericer<MyCls> MyGen = new Genericer<MyCls>();
Console.WriteLine(MyGen.GetItem().Name);
}
}
这句话很重要:int i 和 int i = new int()作为类的成员,也就是字段定义时,是没有区别的,因为会自动完成初始化,此时的int i中的i被默认为0;而如果int i和int i = new i()作为一个方法的变量定义时,二者是有区别的,此时的new i()会进行初始化处理,这是new作为运算符的作用之一
二 base 和 this
1 base : 1 让子类在构造含数中首先执行父类的构造含数
2 访问父类的公开和受保护的成员,但是只局限在构造函数、实例方法和实例属性访问器中
base可以指向的父类的方法有两种情况:一是有重载存在的情况下,base将指向直接继承的父类成员的方法,例如Audi类中的ShowResult方法中,使用base访问的将是Car.ShowResult()方法,而不能访问Vehicle.ShowResult()方法;而是没有重载存在的情况下,base可以指向任何上级父类的公有或者受保护方法,例如Audi类中,可以使用base访问基类Vehicle.Run()方法。
2 this 主要是访问本类的成员。
1
- 限定被相似的名称隐藏的成员
- //限定被相似的名称隐藏的成员
public Vehicle(string name, int speed)
{
this.name = name;
this.speed = speed;
}
- 将对象作为参数传递到其他方法
- public void Run()
{
//传递当前实例参数
Action.ToRun(this);
}
- 声明索引器
- //声明索引器,必须为this,这样就可以像数组一样来索引对象
public string this[int param]
{
get{return array[param];}
set{array[param] = value;}
} -
- 尽量少用或者不用base和this。除了决议子类的名称冲突和在一个构造函数中调用其他的构造函数之外,base和this的使用容易引起不必要的结果。
- 在静态成员中使用base和this都是不允许的。原因是,base和this访问的都是类的实例,也就是对象,而静态成员只能由类来访问,不能由对象来访问。
- base是为了实现多态而设计的。
- 使用this或base关键字只能指定一个构造函数,也就是说不可同时将this和base作用在一个构造函数上。
- 简单的来说,base用于在派生类中访问重写的基类成员;而this用于访问本类的成员,当然也包括继承而来公有和保护成员。
- 除了base,访问基类成员的另外一种方式是:显示的类型转换来实现。只是该方法不能为静态方法。
- BASE 在一个方法里如果基类实现了基父类的方法的话。那子类会访问基类的成员,如果没实现。则访问基父类的成员。
- string类型重载了==操作符,在类型比较是比较的是实际的字符串,而不是引用地址
- 通常可以使用Type.IsValueType来判断一个变量的类型是否为值类型,典型的操作为:
- Type type = aStruct.GetType();
if (type.IsValueType) - .NET中以操作符ref和out来标识值类型按引用类型方式传递,其中区别是:ref在参数传递之前必须初始化;而out则在传递前不必初始化,且在传递时必须显式赋值。
- 值类型与引用类型之间的转换过程称为装箱与拆箱,这值得我们以专门的篇幅来讨论,因此留待后文详细讨论这一主题。
- sizeof()运算符用于获取值类型的大小,但是不适用于引用类型。
值类型有两种表示:装箱与拆箱;引用类型只有装箱一种形式- 值类型是密封的(sealed),因此值类型不能作为其他任何类型的基类,但是可以单继承或者多继承接口;而引用类型一般都有继承性。
- 值类型不具有多态性;而引用类型有多态性。
- 值类型变量不可为null值,值类型都会自行初始化为0值;而引用类型变量默认情况下,创建为null值,
- 一般来说参数个数都是固定的,定义为集群类型的参数可以实现可变数目参数的目的,但是.NET提供了更灵活的机制来实现可变数目参数,这就是使用param修饰符。可变数目参数的好处就是在某些情况下可以方便的提供对于参数个数不确定情况的实现,例如计算任意数字的加
- 使用方式为 public void test(string strwhere, params int[] arrayIds)
- param修饰的参数必须为一维数组,事实上通常就是以群集方式来实现多个或者任意多个参数的控制的,所以数组是最简单的选择;
- param修饰的参数数组,可是是任何类型。因此,如果需要接受任何类型的参数时,只要设置数组类型为object即可;
- param必须在参数列表的最后一个,并且只能使用一次。
using只能用于实现了IDisposable接口的类型,禁止为不支持IDisposable接口的类型使用using语句,否则会出现编译时错误;
· using语句适用于清理单个非托管资源的情况,而多个非托管对象的清理最好以try-finnaly来实现,因为嵌套的using语句可能存在隐藏的Bug。内层using块引发异常时,将不能释放外层using块的对象资源。
· using语句支持初始化多个变量,但前提是这些变量的类型必须相同,例如:
概念:虚方法
虚方法就是以virtual关键字修饰并在一个或多个派生类中实现的方法,子类重写的虚方法则以override关键字标记。虚方法调用,是在运行时确定根据其调用对象的类型来确定调用适当的覆写方法。.NET默认是非虚方法,如果一个方法被virtual标记,则不可再被static、abstrcat和override修饰。
概念:抽象方法
抽象方法就是以abstract关键字修饰的方法,抽象方法可以看作是没有实现体的虚方法,并且必须在派生类中被覆写,如果一个类包括抽象方法,则该类就是一个抽象类。因此,抽象方法其实隐含为虚方法,只是在声明和调用语法上有所不同。abstract和virtual一起使用是错误的。
如果基访问引用的是一个抽象方法,则将导致编译错误。
- 虚方法不能是静态的、密封的。
- 覆写实现的多态确定于运行时,因此更加的灵活和抽象;重载实现的多态确定于编译时,因此更加的简单和高效。二者各有特点与应用,不可替代。