C#学习笔记

【持续更新】
【2024-07-19】 新建

  1. 对象初始化语句的执行总是在构造函数执行之后,如:
    class Point
    {
        public int X = 1;
        public int Y = 2;
        public Point(int x, int y)
        {
            X = x;
            Y = y;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Point p = new Point(3,4) {X = 5, Y = 6};
            Console.WriteLine($"p.X = {p.X}, p.Y = {p.Y}");
        }
    }
// X,Y先被实例化为1,2
// 再调用构造函数赋值为3,4
// 最后由初始化语句赋值为5,6
// 所以输出 p.X = 5, p.Y = 6
  1. 如果坚持使用.NET类,就不需要为类编写析构函数(如果使用了非托管资源,就必须要)

  2. readonly修饰符与const修饰符的区别

  • 前者在内存中有存储位置,后者没有
  • 前者可以是实例字段也可以是静态字段,后面总是静态的
  • 前者可以在运行时(仅构造函数)更改,后者不允许更改。
    总之,const 更像是c语言的宏定义; readonly 更像是c语言中的const
  1. 类的属性字段没有存储位置,其行为更像是方法,而不是字段

  2. 除了特殊类,所有的类都派生自object类,object类是唯一的非派生类

  3. new关键字可以用来屏蔽基类的成员及成员函数;

  4. 派生类若要访问基类隐藏的成员,要使用base关键字。

  5. 派生类的实例要访问隐藏的基类成员,可以将派生类引用强制转换成基类引用后进行访问。

  6. 将派生类引用强制转换成基类引用后,访问虚方法仍然访问的是派生类的虚方法!!!!!

  7. 属性也可以声明为虚属性(virtual/override)

  8. 创建一个实例的过程,先初始化对象的所有实例成员, 再调用基类的构造函数,再调用自己的构造函数

  9. 实例成员若没有初值,则会默认初值0(对于引用则为NULL)

  10. 派生类的构造函数若没有初始化语句,则将调用基类的无参构造

    class BaseClass
    {
        public BaseClass()
        {
            Console.WriteLine("base construct: default");
        }
        public BaseClass(string name)
        {
            Console.WriteLine("base construct: " + name);
        }
    }
    class DerivedClass : BaseClass
    {
        public DerivedClass(string name)
        {
            Console.WriteLine("derived construct: " + name);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            DerivedClass c = new DerivedClass("hello");
            Console.ReadLine();
        }
    }

//输出 :
// base construct: default
// derived construct: hello

  1. 派生类的构造函数初始化语句可以使用关键字base或者this指明使用哪个构造函数
    class BaseClass
    {
        public BaseClass(int x)
        {
            Console.WriteLine("base int: {0}", x);
        }
    }
    class DerivedClass : BaseClass
    {
        public DerivedClass(int x):base(x)
        {
            Console.WriteLine("derived int: {0}", x);
        }

        public DerivedClass(float x) : this((int)x)
        {
            Console.WriteLine("derived float: {0}", x);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            DerivedClass c = new DerivedClass(1.3f);
            Console.ReadLine();
        }
    }

// 输出:
// base int: 1
// derived int: 1
// derived float: 1.3
  1. 类的声明默认为internal,而不是public

  2. 注意访问级别

public class Myclass
{
    public             int A1;  // 所有可访问
    private            int A2;  // 仅类内部可访问
    protected          int A3;  // 仅该类及其继承类可访问
    internal           int A4;  // 仅该程序集可访问
    protected internal int A5;  // 该类或其继承类或该程序集可访问
}
  1. 抽象类(abstract) 必须实现(override)所有抽象成员后才能实例化

  2. 方法、属性、事件、索引器都可以被抽象,而数据成员不可以

  3. 当需要指明类不能被继承时,使用sealed修饰符标注(密封类)

  4. 静态类(static标记类)可以有一个静态构造函数(无参)

  5. 扩展方法、以及声明扩展方法的类必须是静态的、可访问的。

  6. 标准数字格式说明符

  7. 值类型与引用类型

    尤其注意,结构struct是值类型,class是引用类型

  8. 无后缀的实属字面常量是double,而不是float!!!

  9. 引用比较相等时,一般只比较引用是否相等(浅比较),而string与委托是例外,会比较内容是否相等(深比较)

  10. implicit与explicit可用于定义类型的隐式转换与显式转换,定义转换时需要加public static!!!

    运算符重载时也是如此,例如:

  11. typeof用于了解类的特征

  12. switch 不允许从一个分支直接进入另一个分支

  13. 类class与结构struct的区别:

  • class是引用类型,struct是值类型
  • struct的无参构造由系统默认提供,不可重定义、删除。
  • class一旦定义了任意构造函数,系统就不会提供默认的无参构造,需要用户自己提供
  • struct不可声明析构函数,class可以
  • struct不可派生其它struct
  • struct声明时,不可有初始化语句,如:
  1. 枚举enum底层类型默认为int,可以更改为其它:

  2. 枚举类型若表示位域定认,最好加上[Flag]标志。若不加可能会得到不想要的效果,如下:

    加上后:

  3. 不同的枚举类型不能比较,编译错误(哪怕具有相同名字的域)

  4. 数组一旦创建,大小就固定了

  5. 数组是引用类型,但其元素可以值类型也可为引用类型

  6. 交错数组的实例化

  7. foreach的迭代变量是只读的

  8. 数组常用的属性与方法

posted @ 2024-07-19 21:51  坚持梦想的蜗牛  阅读(9)  评论(0编辑  收藏  举报