1.抽象abstract与接口interface,“面向抽象编程”本质上是对数据的抽象化,“面向接口编程”本质上是对行为的抽象化。
a)抽象关注相同的“类”,父子类可归为同一类事物。
b)接口关注相同的“行为”,行为可能是不同的类。
c)接口内不能定义字段,但能定义自动实现属性:{get;set}
2.where T : class, new()对类的约束,必须是类,且有一个无参构造函数
```
where T: struct T必须是一个结构类型
where T: class T必须是一个类(class)类型,不是结构(structure)类型
where T: new() T必须要有一个无参构造函数
where T: NameOfBaseClass T必须继承名为NameOfBaseClass的类
where T: NameOfInterface T必须实现名为NameOfInterface的接口
```
3.接口不能定义字段(int count),可以定义属性(int Count{get;set;})
4.C# 方法/属性/字段 默认访问级别 : private
C# 类默认访问级别 : internal
public:访问不受限制。
protected:访问仅限于包含类或从包含类派生的类型。
Internal:访问仅限于当前程序集。
protected internal:访问限制到当前程序集或从包含派生的类型的类别。
private:访问仅限于包含类型。
4.enum可常用,作为if或者switch的条件
5.泛型:理解为模型,具有相同特征的类和方法的模型,如类的模型,方法的模型。
a)声明类型参数--泛型的消费者需要提供参数类型来把占位符填充上(T表示Type,也可以用其他字符作为占位符,只是强烈建议用T)。b)所有的泛型实例在运行的时候都是封闭的(也就是占位符已经填充的),JIT编译(IL转换生成机器码)的时候,会把上面编译生成的占位符替换成具体的数据类型。c)泛型约束:where T:d)泛型的类也可以被继承,子类也可以继续保持开放(也就是继续使用原占位符)e)泛型方法可以出现在普通类中,不一定在泛型类中,但在大多用于泛型类中f)抽象类也只是针对相同的类而不是多个不同的类。g)在类库中用得比较多的地方是集合。
6.express body:方法体使用=>简写
7.in,out,ref:让值类型能像引用类型一样传参(传递引用地址)
in修饰方法参数时,表示参数是传进来的,读变量,只能用,不能修改
out:表示参数是需要传出去,可以不需要初始化,目前可用tuple代替
ref:可传入传出可修改
8.lamda表达式:看成一个匿名方法,但有区别,更简洁(有时候{}都可以省略)
a)三个部分组成:放在括号内在参数列表,=》,c#语句
如:
(param1,param2) => {return param1+param2;}
b)常常与Func和Action一起使用
c)当lamda表达式使用外部变量时,此变量叫被捕获的变量,会形成闭包,变量的值会在委托被被调用的时候计算。而不是捕获时。生命周期与委托一样长。
int i = 2;
Func<int, int> foo = (x) => x * i;
i = 10;
Console.WriteLine(foo(3));//输出30,而不是6
9.匿名方法:
与lamda表达式差不多,也是主要用在委托中。但写方法体的时候,一定要用大括号{},而lamda表达式可以更简洁。有时候{}都可以省略.现在匿名方法用得越来越少。
delegate void Del(int x);Del d = delegate(int k) { /* ... */ };
//无参数列表的,返回类型为int的匿名方法。dataDelegate += delegate () { Console.WriteLine(\"我是匿名方法退票\"); return 50; };
10.值类型与引用类型
a)值类型:保存在栈中,结构和枚举也属于值类型。变量保存栈的值,赋值会创建新的栈。
b)引用类型:保存在堆中,变量只保存引用地址(引用类型变量名称本身存在栈中),所以赋值只会把引用地址传过来,还是同一个个堆内存。
c)装箱:把值类型的副本装起来,变为引用类型,常常用objec,在堆中生成副本
d)拆箱:把引用类型的副本拆出来,转为值类型,在栈中生成副本
f)值类型作为
11.结构:结构通常用来封装小型相关变量组
a)结构中也可以有字段/属性/方法,与类差不多与类同级,但结构是值类型
b)结构中的字段不能初始化
c)结构中的不允许自己定义无参构造函数
12.枚举:枚举能够使代码更加清晰,它允许使用描述性的名称表示整数值,封装小型整型数据
a)枚举类型的枚举成员均为静态,且默认为Int32类型,与类同级,但枚举是值类型
b)枚举中不能定义字段属性方法
c)枚举值默认是从0开始的自增长除非指定
### 13.new和override:看起来都好像是对基类同名方法的重写,但有区别
new能对所有基类方法屏蔽,override只能覆盖重写virtual,abstract,override修饰的。
new的新方法可能与基类无关,只是纯粹隐藏,,向上转型时调用还是会执行基类中override的方法。
override更偏向于先声明表示有些功能,更多具体功能放子类中实现,向上转型时调用会执行子类中override的方法。
### 14.virtual和abstract:看起来都是用来修饰基类的方法,以便让子类覆盖重写。,但有区别
a)virtual修饰的方法必须有实现(哪怕是仅仅添加一对大括号),而abstract修饰的方法一定不能实现。
b)abstract关键字只能用在抽象类中修饰方法,并且没有具体的实现。抽象方法的实现必须在派生类中使用override关键字来实现。abstract修饰类时不能被实例化。
15.byte,bit
16.c#编译运行
17.代码组织结构:在netcore命令行中,使用要记得这种结构操作:.sln/.csproj/.cs
17.ToString()方法重写:在自己定义的类中override能有一些特殊作用,ToString()是object类的方法,所以类都可重写。
18.向上转型:这样理解。
a)子类创建对象时,从内存上看,其实里面包含基类对象内存区
b)当子类赋给基类对象时,基类的对象引用指定子类对象中包含的基类对象内存块。
c)此时调用基类方法,如果基类方法被子类override,则会执行子类同名方法(实现接口虽然不用写override,但默认如此)。如果基类方法被子类new,还是执行父类同名方法。
d)不能调用任何子类中新的方法或属性或字段(未在基类中声明过的)。
e)向下转型不安全,编译没错,但执行时会报错。不考虑使用!!!
19.this和base:基本上都是两个作用,但范围不一致
a)调用构造函数(除了静态构造函数)
在构造函数后面使用“:this(参数1…) 和base(参数1…)”,注意使用位置
如public Animal(string name,string age):this(name)
子类初始化时也就是执行子类构造函数之时,如果未显示base调用基类的哪一个构造函数,会默认先调用基类无参构造函数
b)代表对象
this代表类自身对象,base代表基类对象
“`
public Animal()
{
Console.WriteLine(“无参构造函数”);
}
public Animal(string name)
{
Console.WriteLine(name);
}
public Animal(string name, string sing) : this(name) //1.调用自己的构造函数,注意位置{Console.WriteLine(name + \":\" + sing);this.Look(); //2.代表自身对象,调用自己的方法}public void Look(){Console.WriteLine(\"animal look\");}}class Dog:Animal{public Dog(string name):base(name) //3.调用基类构造方法,如果不显示指定,默认自动调用基类无参构造函数base(){this.Look();base.Look(); //4.代表基类对象,调用基类方法}public new void Look(){Console.WriteLine(\"dog look\");}}
“`
### 20.静态成员:static关键字修饰的字段,属性,方法,索引
a)静态成员在引用其他静态静态成员或者实例化之前预先创建。
b)静态成员的内存是共享的,所以修改一个静态成员,会修改所有使用到它的位置。
c)静态函数不能调用非静态成员:因为静态成员是提前创建,并不能知道非静态成员/类实例是否创建
d)静态构造函数:
在引用其他静态静态成员或者实例化之前,都会执行,常用初始化赋值其他静态字段不能使用this,base调用其他构造函数,因为不能保证this/base的对象已经初始化。静态构造函数(三无)无访问修饰符,无返回值,无参数
20.静态类:常用来作为1基础工具类(如Math)或2扩展方法
a)内部成员必须全部是静态的
b)有仅只能有一个三无参构造函数,其他有参构造函数不能有
c)不能继承静态类。
d)使用实例2:扩展方法
//为Dog扩展方法,//1.扩展方法所在的类必须是静态类//2.扩展方法本身必须是静态方法//3.扩展方法的第一个参数必须是:this+类名static class HowWalk{public static void Walk(this Dog dog,int legnums){Console.WriteLine($\"为dog扩展walk方法:用{legnums}条legs走路\");}}
Dog dog = new Dog(\"dog\");dog.Walk(4); //像自己的Dog类方法一样使用
21.运算符重载:利用现有的某种操作符,针对自定义的类或结构,定义某种运算操作。
a)方法定义访问修饰符必须是public
b)方法必须是静态的
c)使用关键字“operator 操作符”
//方法参数是操作符的输入,返回Animalstruct Feature{public int Age { get; set; }public void Walk(){Console.WriteLine(\"I can walk\");}public static Feature operator +(Feature f1, Feature f2){int age= f1.Age + f2.Age;return new Feature() { Age = age };}}
Feature feature1 = new Feature() { Age=20};Feature feature2 = new Feature() { Age = 30 };Feature feature3 = feature1 + feature2;Console.WriteLine(feature3.Age);
22.可空类型:泛型结构的值类型
a)语法:值类型?或者Nullable<值类型>
b)是结构,所以是值类型
23.集合:所以集合基于IEumerable接口,相当于Object之于所有类型
a)ArrayList,List/List,Dictionry<k,v>,HashTable(也是KV)
b)ArrayList:动态数组,以动态改变数组的长度,value是object类型,有装箱拆箱过程,类型不安全
c)针对arraylist的缺点,出了List类型,泛型在运行的一定是可知类型
d)Dictionary是kv键值对的一种泛型,内含对象是keyvalpair结构体对象
e)Hashtale的kv都是object类型,所以也会存在装箱拆箱过程,但因为是hash算法存储,还是比较好。
f)还有其他集合,按需求使用,比如,LinkedList,SortedList,Stack,Queue。。。