当前位置导航:炫浪网>>网络学院>>编程开发>>Visual C#教程

分享:C#技术内幕 学习笔记

  
  引用类型是类型安全的指针,它们的内存是分配在堆(保存指针地址)上的。
  String、数组、类、接口和委托都是引用类型。
  
  强制类型转换与as类型转换的区别:当类型转换非法时,强制类型转换将抛出一个System.InvalidCastException异常,
  而as不会抛出异常,它返回一个null值。
  
  用using创建别名:using console = System.Console;
  
  访问限定符:
  public 该成员可以被其他任何类访问
  protected 该成员只能被其派生类访问
  private 该成员只能被本类的其他成员访问
  internal 该成员只能在当前编译单元的其他成员访问
  
  带参数列表和返回值的Main方法:
  class Test
  {
  public static int Main(string[] args)
  {
  foreach (string arg in args)
  {
  ...
  }
  }
  }
  
  构造函数(constructor)包括实例构造函数和静态构造函数。
  构造函数与类名相同,且不能有返回值。例:
  class TestClass
  {
  TestClass() //实例构造函数:可以访问静态成员和实例成员,用于初始化实例成员
  {
  ...
  }
  
  static TestClass() //静态构造函数:只能访问静态成员,用于初始化静态成员
  {
  ...
  }
  }
  
  类的静态成员属于类所有,不必生成实例就可以访问,它是在载入包含类的应用程序时创建的,但静态方法不能访问类的实例变量和方法。通常,静态变量是在定义时就赋初始值的。
  
  类的实例成员属于类的实例所有,不创建实例对象就无法对其进行访问,实例成员可以访问类的静态成员和其它实例成员。
  
  调用基类的析构函数:
  class A
  {
  public A()
  {
  ...
  }
  }
  
  class B
  {
  public B(): base() //调用基类的析构函数
  {
  ...
  }
  }
  
  常量:其值是在编译时设定的,必须是数值文字。默认状态下常量是静态的。例:
  class A
  {
  public const double pi = 3.1415;
  }
  
  常量是编译时就确定的值,只读字段是在运行才能确定的值。比如运行时才能确定的屏幕分辨率。
  
  只读字段只能在类的析构函数中赋值。
  
  静态只读字段:
  class A
  {
  public static readonly int ScreenWidth; //静态只读字段
  static A()  //静态析构函数
  {
  ScreenWidth = 1024; //在静态析构函数中初始化
  }
  }
  
  在类的继承中,类的析构函数是不会被继承的。
  
  一个派生类只能从一个基类继承,不能同时从多个基类继承,但可以通过继承多个接口来达到相同目的。实现多继承的唯一方法就是使用接口。例:
  class MyFancyGrid: Control, ISerializable, IDataBound
  {
  ...
  }
  
  密封类是不能继承的类,抽象类不能被定义为密封类,且密封类的私有成员不能用protected修饰,只能用private。例:
  sealed class A
  {
  ...
  }
  
  关键字ref和out用于指定用引用方式传递方法的参数。
  它们的区别是:ref参数必须初始化,而out参数不需要初始化。所以在方法处理代码依赖参数的初始化值时使用ref,不依赖初始化值时使用out。
  
  对out参数即使在传递前对其进行了初始化,其值也不会传递到方法处理函数内部。传递时系统会将其设为未初始化。所以在方法内部必须对out参数进行初始化。
  
  方法重载时,必须参数数目和参数类型其中之一不同,返回值不同不能作为重载。
  
  C#不支持方法的默认值,只能通过方法重载来实现。例:
  class A
  {
  int Method(int a)
  {
  ...
  }
  
  void Method(int a, int b) //参数数目不同
  {  //返回值不同不能作为重载
  ...
  }
  }
  
  params参数用于一个不定数目参数的方法,一般后面跟一个数组。例:
  class A
  {
  public void Method(params int[] i)
  {
  ...
  }
  }
  
  方法的覆盖:指派生类覆盖基类的同名方法,有二种方法
  1)第一种是在派生类要覆盖的方法前面加new修饰,而基类不需要作任何改动。
  这种方法的缺点是不能实现多态。例:
  class A
  {
  public void Method() //无需任何修饰
  {
  ...
  }
  }
  
  class B: A  //从基类继承
  {
  new public void Method() //覆盖基类的同名方法
  {
  ...
  }
  }
  
  class TestClass
  {
  A Instance = new B();
  Instance.Method(); //这时将调用类A的Method方法,而不是类B的Method方法
  }
  
  2)第二种是在派生类要覆盖的方法前面加override修饰,而基类的同名方法前面加virtual修饰。
  这样就能实现多态,例:
  
  class A
  {
  virtual public void Method()  //基类定义虚方法
  {   //虚拟方法不能定义为private,因为private成员对派生类是无法访问的
  ...
  }
  }
  
  class B: A   //从基类继承
  {
  override public void Method()  //派生类覆盖基类的同名虚方法
  {
  ...
  }
  }
  
  class TestClass
  {
  protected void Test()
  {
  A Instance = new B();  //定义一个实例,类型为基类,从派生类创建
  //派生类总是能够向上转换为其基类
  Instance.Method();  //将调用派生类B的Method方法,而不是基类的,这就是多态
  }
  }
  
  说明:new修饰的方法覆盖不能实现多态的原因,是因为使用new时编译器只会实现早期绑定(early binding)。
  
  即调用的方法在编译时就决定了:编译器看到Instance.Method()而Instance的类是A,就会调用类A的Method()方法。
  
  override修饰的方法覆盖可以实现多态的原因,是因为实现了后期绑定(late binding)。
  
  使用override时强制编译器在运行时根据类的真正类型正确调用相应的方法,而不是在编译时。
  
  而基类的同名方法必须加virtual修饰。
  
  类的静态方法可能通过 类名.静态方法名 这种格式来调用,不能使用 实例名.静态方法名 这种方法调用。
  
  因为类的静态方法为类所有(是属于类本身的),而非实例所有(不是属于类的实例的)。
  
  类的静态方法可以访问类的任何静态成员,但不能访问类的实例成员。
  
  C#中类的变量称为字段。类的public变量称为类的公共字段。
  
  类的属性由一个protected(也可以是private)字段和getter和setter方法构成:
  class Address
  {
  protected string zipCode; //protected字段,注意大小写
  public string ZipCode
  {
  get  //getter方法
  {
  return zipCode;
  }
  set  //setter方法
  {
  zipCode = value; //被传递的值自动被在这个value变量中
  }
  };
  }
  
  只读属性是指省略setter方法的属性,只读属性只能读取,不能设置。
  
  属性也可以用限定符virtual,override和abstract修饰,功能同其他类的方法。
  
  属性有一个用处称为懒惰的初始化(lazy initialization)。即在需要类成员时才对它们进行初始化。如果类中包含了很少被引用的成员,而这些成员的初始化又会花费大量的时候和系统资源的话,懒惰的初始化就很有用了。
  
  C#中数组对象共同的基类是System.Array。
  
  将数组声明为类的一个成员时,声明数组与实例化数组必须分开,这是因为只能在运行时创建了类的实例对象之后,才能实例化数组元素值。
  
  声明:
  int[] intArray; //一维数组
  int[,,] int3Array; //三维数组
  初始化:
  intArray = new int[3] {1,2,3};
  int[,] int2Array = new int[2,3] {{1,2,3},{4,5,6}}; //声明时可以初始化
  遍历:
  1)一维数组
  for (int i = 0; i < intArray.Length; i++); //Array.Length返回数组所有元素的个数
  foreach (int i in intArray);
  for (int i = 0; i < intArray.GetLength(0); i++);//Array.GetLength(0)返回数组第一维的个数
  2)多维数组
  for (int i = 0; i < int3Array.GetLength(0); i++) //遍历三维数组
  for (int j = 0; j < int3Array.GetLength(1); j++)
  for (int k = 0; k < int3Array.GetLength(2); k++)
  {
  ...
  }
  数组的维数就是该数组的秩(Rank)。Array.Rank可以返回数据的秩。
  锯齿数组(jagged Array)是元素为数组的数组,例:
  int[][] jaggedArray = new int[2][]; //包含二个元素,每个元素是个数组
  jaggedArray[0] = new int[2]; //每个元素必须初始化
  jaggedArray[1] = new int[3];
  for (int i = 0; i < jaggedArray.Length; i++) //遍历锯齿数组
  for (int j = 0; j < jaggedArray[i].Length; j++)
  {
  ...
  }
  
  类的属性称为智能字段,类的索引器称为智
相关内容
赞助商链接