• 类成员
  • 实例成员和静态成员
  • 成员常量
  • 属性
  • 构造函数
  • this
  • readonly 修饰符
  • 索引器
  • 访问器
  • 封装、继承、多态

类成员

数据成员

函数成员

image-20220805182134130

静态成员

static 修饰

类的所有实例共享静态成员。

这也就导致了如果我们修改静态成员时,其他实例读到到也是这个修改的。即数据只有一份。

静态成员的生命周期和实例没有关系。即实例是否产生或销毁对静态成员没有影响。

image-20220805182512178

static 修饰的为静态成员

声明 d1、d2 两个实例,在右图的堆里会开辟两个空间去存放两个实例。每个实例都有自己的实例成员Mem1。

共用Mem2静态成员。

常量成员

常量成员不能声明为静态成员。

与本地常量类似,用于初始化成员常量的值在编译时必须是可计算的,通常是一个预定义的简单类型或由他们组成的表达式。

“然而,成员常量比本地常量更有趣,因为它们表现得像静态值。它们对类的每个实例都是“可见的”,而且即使没有类的实例也可以使用。与真正的静态量不同,常量没有自己的存储位置, 而是在编译时被编译器替换。这种方式类似于C和C++中的#define值。”

1
2
3
4
5
6
7
8
9
10
static const double PI 3.14; // 错误:不能将常量声明为static

class MyClassContainer {
static public int Var = 1;
public const int Var1 = 2;
}

MyClassContainer.Var1


属性

类成员

属于函数成员

包括两个访问器(get set)

image-20220806091743065

最少保留一个访问器

只有 get 代表属性只读

属性不分配内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class MyClassContainer {
public int MyValue {
private int inValue = 2; // 后备字段可以是一个private的字段
get {
return inValue;
}
set {
inValue = value;
}
}
}

var MyClassContainer2 = new MyClassContainer();
Console.WriteLine("publicField is: {0}", MyClassContainer2.MyValue);
MyClassContainer2.publicField *= 4;
Console.WriteLine("publicField is: {0}", MyClassContainer2.MyValue);

/**
* output publicField is: 2
publicField is: 8
*/

自动实现数据

后备字段可以隐藏

属性被分配了内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MyClassContainer {
public int MyValue {
get;
set;
}
}

var MyClassContainer2 = new MyClassContainer();
Console.WriteLine("publicField is: {0}", MyClassContainer2.MyValue);
MyClassContainer2.publicField *= 4;
Console.WriteLine("publicField is: {0}", MyClassContainer2.MyValue);

/**
* output publicField is: 2
publicField is: 8
*/

静态属性

属性可以通过 static 修饰 变成静态属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class C1 {
static public int MyValue {
set;
get;
}
}
class Program {
static void Main (){
Console.WriteLine("=========================");
Console.WriteLine(C1.MyValue);
C1.MyValue = 100;
Console.WriteLine(C1.MyValue);
}
}

构造函数(constructor)

实例化的时候会执行

没有返回值,不需要显式的去写 void

函数名和类名保持一致

存在参数

1
2
3
4
5
6
7
8

class Program {
static void Main (){
var c2 = new C2();
var c21 = new C2(2);
var c22 = new C2("name");
}
}

隐式构造函数

如果没有显式的自定义构造函数,编译器会提供一个默认构造函数

没有参数;

方法体为空。

静态构造函数

构造函数也可以声明为static。实例构造函数初始化类的每个新实例,而static构造函数初始化类级别的项。通常,静态构造函数初始化类的静态字段

不能有其他修饰符 static constructor cannot have an access modifier

不能有参数 The static constructor must be parameterless

只能有一个静态构造函数(可以和实例构造函数同时存在)

析构函数

.net 不支持

this关键字

this关键字在类中使用,是对当前实例的引用。

不能在静态成员中使用。

索引器

自带访问器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Program {
static void Main () {
var c3 = new C3();
Console.WriteLine("LastName: {0}", c3[0]); // 通过索引访问
c3.LastName = "eric";
Console.WriteLine("LastName: {0}", c3[0]);

Console.WriteLine("=========================");

Console.WriteLine("FirstName: {0}", c3.FirstName); // 通过.运算符进行访问
c3.FirstName = "Xu";
Console.WriteLine("FirstName: {0}", c3.FirstName);
}
}

class C3 {
public string LastName; // 声明三个字段
public string FirstName;
public string city;
// public string
public string this[int index] { // 这里是this 其实显式的做某种绑定,以索引的形式展示
set {
switch (index) {
case 0:
LastName = value;
break;
case 1:
FirstName = value;
break;
case 2:
city = value;
break;
default:
throw new ArgumentOutOfRangeException("index");
}
}
get {
switch (index) {
case 0:
return LastName;
case 1:
return FirstName;
case 2:
return city;
default:
throw new ArgumentOutOfRangeException("index");
}
}
}
}

分部语法

奇怪的知识

总结

1,static

要区分清楚是否static

UserDoctorLogstatic 不在实例之内,是跟随着class的声明而定义。

2,constructor

构造函数;实例化的过程中必然执行构造函数。接收 new class 时的参数。但没有返回值。

可以重载。

3,属性

属性是重点。

image-20220805182134130

属性不是字段,而是方法的一类。

必须有装饰器跟随

最简实现

1
2
3
4
5
6
class C4 {
public int MyValue {
get;
set;
}
}