#Day1 2024.04.16

ctrl + k + c //注释(可多行

ctrl + k + u //取消注释

ctrl + k + d //快速对齐

ctrl + l //删除行

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _01_project
{

internal class Program
{
static void Main(string[] args)
{
string name = "战马";
int chinese = 100;
char gender = '男';
double pi = 3.14;
decimal money = 5000m;
bool b = false;

Console.WriteLine(name);
Console.WriteLine(chinese);
Console.WriteLine(gender);
Console.WriteLine(pi);
Console.WriteLine(money);
Console.WriteLine(b);
Console.ReadKey();

//一次性生成相同多个同类型的数据
int chinese,math,english,physic;

//var推断类型:根据等号后面的值推断等号前面的变量类型
var name = "战马";
var chinese = 100;

}
}
}

变量命名规范

  • Camel:多个单词组合变量,第一个单词首字母小写,其余的首字母大写。
  • Pascal:单个单子是指变量名,首字母大写。

#Day2 2024.04.17

占位符

  • ​ 使用{number}表示占位符(形式上比C++的%d、%f、%lf之类的好,但是内容是一样的)

  • ​ 使用 “$” :$符号将{变量名}解析成了变量所对应的值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace project1
    {
    internal class Program
    {
    static void Main(string[] args)
    {
    string name = "张三";
    double height = 190;
    Console.WriteLine("我的身高是{1},我的名字是{0},他的名字也是{0}",name ,height);
    Console.ReadKey();

    Console.WriteLine($"我的名字是{name}");

    Console.ReadKey();
    }
    }
    }

转义符

  • /

  • @

逻辑运算符

1
2
3
4
5
6
&& 和 & 
|| 和 |

前者比后者效率更高
eg.前者判断&&前面为false的话直接输出 false,&则要将前后全部判断一遍才输出
前者判断||前面为true的话直接输出 true, |则要将前后全部判断一遍才输出

#Day3 2024.04.19

垃圾回收(GC):会帮助我们回收长期不用的内存空间

Try - Catch - Finally

  • Try : 尝试性的捕获异常。如果出现了异常,则立即跳到Catch中执行。入伙Try中的代码,没有出现异常,则不会进入Catch执行
  • Catch : 异常出现以后,要执行的代码
  • Finally : 不管有内有异常,都要执行,多用于写资源释放
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 异常捕获
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("请输入数字");
try
{
int num = Convert.ToInt32(Console.ReadLine());
Console.WriteLine($"您输入的数字是{num}");
}
catch
{
Console.WriteLine("输入的字符串不能转化为数字,程序结束!!!");
}
finally
{
Console.WriteLine("不管出现或者不出现异常,我都得执行");
}
}
}
}

#Day4 2024.04.20

  • 单步调试:从第一行代码开始,一行一行的进行调试,便于我们理解整个程序的运行
  • 断点调试:在我们指定的位置,开始调试,便于我们快捷的找到程序的问题所在

枚举类型

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
51
52
53
54
55
56
57
58
59
60
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 枚举类型
{
internal class Program
{
enum Gender//1、定义一个数据类型
{
男,

}

enum QQstate
{
OnLine,
OFFLine,
Busy,
QMe,
Leave,
隐身
}
enum Seasons
{
春,
夏,
秋,

}

static void Main(string[] args)
{
//2、声明枚举类型的变量
//3、给枚举类型的变量赋值
//4、使用枚举类型的变量
//Gender gender = Gender.男;

Seasons s = Seasons.春;
Seasons s1 = Seasons.夏;
Seasons s2 = Seasons.秋;
Seasons s3 = Seasons.冬;

//枚举类型和数值类型兼容
int n1 = (int)s;
int n2 = (int)s1;
int n3 = (int)s2;
int n4 = (int)s3;

Console.WriteLine(n1);
Console.WriteLine(n2);
Console.WriteLine(n3);
Console.WriteLine(n4);

Console.ReadKey();
}
}
}

  • 堆的速度比栈快

#Day5 2024.04.21

Out参数

Out

1、需要在方法内部返回多个值,并且这些值的数据类型可能不一样。
2、out参数在方法的内部,必须为其赋值,方法的外部可以不赋值。

OUT的用法

  • OUT在函数里必须进行赋值操作!
  • OUT是引用传递而非值传递
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
51
52
53
54
55
56
57
58
59
60
61
62
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _07_out参数
{
internal class Program
{
static void Main(string[] args)
{
//out:
// 1、需要在方法内部返回多个值,并且这些值的数据类型可能不一样。
// 2、out参数在方法的内部,必须为其赋值,方法的外部可以不赋值。
//ref params
//需求:写一个方法,求数组的最大值、最小值、总和、平均值
//再返回一个 hello World

//int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
//string str;//= null;
//int[] res = GetMaxMinSumAvg(nums,out str);
//Console.WriteLine(str);

//Console.WriteLine("最大值是{0},最小值是{1},总和是{2},平均值是{3}", res[0], res[1], res[2], res[3]);
//Console.ReadKey();

//实现登录,返回登录是否成功,并返回相应的登录信息
//(1、登录成功 2、用户名错误、3密码错误、4、未知错误)

}

static int[] GetMaxMinSumAvg(int[] numbers,out string msg) //out 表示传出去,传给调用者
////
//这里out和ref一样,都是传递变量地址而非变量值!!!!!😱
////
{
int max = numbers[0];
int min = int.MaxValue;
int sum = 0;
int avg = 0;
for (int i = 0; i < numbers.Length; i++)
{
if (numbers[i] > max)
{
max = numbers[i];
}
if (numbers[i] < min)
{
min = numbers[i];
}
sum += numbers[i];
}
avg = sum / numbers.Length;

int[] res = { max, min, sum, avg };
msg = "hello world";
return res;
}
}
}

Ref参数

ref侧重于,把方法外面的值,带到方法内部进行改变,改变完成后,再带出去。

out侧重于,把方法外面的值,在内部进行改变,改变完成后,再带出去。

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _09_ref参数
{
internal class Program
{
static void Main(string[] args)
{
//double salary = 5000;
////ref 把传递值本身,改变为传递地址。
////ref侧重于,把方法外面的值,带到方法内部进行改变,改变完成后,再带出去。
//JiangJin(ref salary);
//FaKuan(ref salary);

//值类型和引用类型:值传递和引用传递
string[] names = { "周杰伦", "林俊杰", "潘玮柏", "刘德华", "Rapper" };
ChangeNames(names);
Console.WriteLine(names[0]);
Console.ReadKey();
}


static void ChangeNames(string[] names)
{
names[0] = "hello World";
}

static void JiangJin(ref double salary)
{
salary += 500;
}
static void FaKuan(ref double salary)
{
salary -= 200;
}
}
}

Params参数

Params 把实参列表中传入的单个元素,都认为是数组中的组成元素
1、插入实参列表中的每一个参数的类型,必须跟形参列表中数组的类型一致。
2、params可变参数,必须是形参列表中的最后一个参数。

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace params参数//把实参列表中的单个元素当作数组中的组成元素
{
internal class Program
{
static void Main(string[] args)
{
//params参数 把实参列表中的单个元素当作数组中的组成元素
//1、插入实参列表中的每一个参数的类型,必须根形参列表中的数组类型一致
//2、params可变参数,不许是形参列表中的最后一个参数

int[] nums = { 1, 2, 3, 4, 5, 6, 7 };
int sum = GetSum(1,1,2,3,4,5,6,7);

Console.WriteLine(sum);
Console.ReadKey();
}

static int GetSum(int msg,params int[] nums)
{
int sum = 0;

for (int i = 0; i < nums.Length; i++) sum += nums[i];

return sum;
}
}
}

Append函数用法

对string类型变量进行更改其值

1:string str = “abxc”

​ str = “ooo”

​ 此时需要在内存中另开辟一块空间存储str = “ooo”

​ 此时str = “abxc”仍任存在于内存中

2:string str = “o”

​ str += “p”

​ 此时需要在内存中另开辟一块空间存储str = “op”

​ 此时str = “o”仍任存在于内存中

因此现有一种特殊的方法避免这种既耗时间又耗空间的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
string str = "张三";
Stopwatch sw = new Stopwatch();
sw.Start();
//00:00:00.1213238 str += "p" 10000

//00:00:00.0034236 Append 10000
//00:00:00.0576661 Append 100000
//00:00:00.3123847 Append 1000000


StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000000; i++)
{
//str += i;
////str = str +i;
sb.Append(i);
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
Console.ReadKey();

#Day6 2024.04.23

今天主要是做飞行棋小程序,无笔记

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
//program

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 飞行棋小程序
{
internal class Program
{
static int[] map = new int[100];
static int[] playerPos = new int[2];
static string[] playerName = new string[2];
static bool[] playerState = new bool[2];
static void Main(string[] args)
{
GameHead();//1
InitialMap();

Console.WriteLine("请输入玩家A的姓名");
playerName[0] = Console.ReadLine();
Console.WriteLine("请输入玩家B的姓名");
playerName[1] = Console.ReadLine();

Console.Clear();

GameHead();
Console.WriteLine($"{playerName[0]}的士兵用A表示");
Console.WriteLine($"{playerName[1]}的士兵用B表示");
//DrawMap(
while (playerPos[0] < 99 && playerPos[1] < 99)
{
if (playerState[0] == false)
{
playTurn(0);
}
else
{
playerState[0] = false;
}

if (playerPos[0] >= 99)
{
break;
}

if (playerState[1] == false)
{
playTurn(1);
}
else
{
playerState[1] = false;
}
}

Win();

Console.ReadKey();

}
static void GameHead()
{
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine("********************************************************");
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("********************************************************");
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("********************************************************");
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine("********************** V1.0 飞行棋 *********************");
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("********************************************************");
Console.ForegroundColor = ConsoleColor.DarkBlue;
Console.WriteLine("********************************************************");
Console.ForegroundColor = ConsoleColor.DarkCyan;
Console.WriteLine("********************************************************");
}

static void InitialMap()
{
int[] luckytrun = { 6, 23, 40, 55, 69, 83 };//幸运轮盘◎ = 1
for (int i = 0; i < luckytrun.Length; i++)
{
map[luckytrun[i]] = 1;
}

int[] landMine = { 5, 13, 17, 33, 38, 50, 64, 80, 94 };//地雷☆ = 2
for (int i = 0; i < landMine.Length; i++)
{
map[landMine[i]] = 2;
}
int[] pause = { 9, 27, 60, 93 };//暂停▲ =3
for (int i = 0; i < pause.Length; i++)
{
map[pause[i]] = 3;
}
int[] timeTunnel = { 20, 25, 45, 63, 72, 88, 90 };//时空隧道卐 =4
for (int i = 0; i < timeTunnel.Length; i++)
{
map[timeTunnel[i]] = 4;
}
}

static void DrawMap()
{
#region 绘制第一横行
for (int i = 0; i < 30; i++)
{
string res = DrawStringMap(i);
Console.Write(res);
}
#endregion

Console.WriteLine();

#region 绘制第一竖列

for(int i = 30;i < 35;i ++ )
{
for(int j = 0;j <29;j ++)
{
Console.Write(" ");
}
Console.WriteLine(DrawStringMap(i));
}

#endregion

#region 绘制第二横行

for (int i = 64; i >= 35; i--)
{
string res = DrawStringMap(i);
Console.Write(res);
}

#endregion

Console.WriteLine();

#region 绘制第二竖列

for (int i = 65; i <= 69; i++)
{
Console.WriteLine(DrawStringMap(i));
}

#endregion

#region 绘制第三横行

for (int i = 70; i < 100; i++)
{
string res = DrawStringMap(i);
Console.Write(res);
}

#endregion

Console.WriteLine();
}

static string DrawStringMap(int i)
{
string res = null;
if (playerPos[0] == playerPos[1] && playerPos[0] == i)
{
res = "<>";
}
//玩家A跟玩家B的坐标不相等,但是玩家A在第地图上

else if (playerPos[0] == i)
{
res = "A";
}
//玩家A跟玩家B坐标不相等,但是玩家B在地图上
else if (playerPos[1] == i)
{
res = "B";
}
else
{
switch (map[i])
{
case 0:
Console.ForegroundColor = ConsoleColor.Green;
res = "□";
break;
case 1:
Console.ForegroundColor = ConsoleColor.Yellow;
res = "◎";
break;
case 2:
Console.ForegroundColor = ConsoleColor.Red;
res = "☆";
break;
case 3:
Console.ForegroundColor = ConsoleColor.Blue;
res = "▲";
break;
case 4:
Console.ForegroundColor = ConsoleColor.Magenta;
res = "卐";
break;
}
}
return res;
}
static Random rNumber = new Random();
static void playTurn(int pNumber)
{
Console.WriteLine("图例:幸运轮盘:◎ 地雷:☆ 暂停:▲ 时空隧道:卐");
DrawMap();

int rr = rNumber.Next(1, 7);
Console.WriteLine($"{playerName[pNumber]}按任意键开始掷骰子");
Console.ReadKey(true);
Console.WriteLine($"{playerName[pNumber]}掷出了{rr}");
Console.ReadKey(true);
Console.WriteLine($"{playerName[pNumber]}按任意键开始行动");
Console.ReadKey(true);

playerPos[pNumber] += rr;
replace();

switch (map[playerPos[pNumber]])
{
case 0://正常情况
Console.WriteLine($"{playerName[pNumber]}踩到了方块上,什么都不发生,平安度过当前回合!!!");
Console.ReadKey(true);
break;
case 1://幸运转盘
Console.WriteLine($"恭喜{playerName[pNumber]}踩到了幸运轮盘!!!!!!改变结局的时候来啦!!!!!");
Console.WriteLine("1----轰炸对方,对方退6格");
Console.WriteLine("2----交换位置,与对方交换位置");
string str = Console.ReadLine();
while (true)
{

if (str == "1")
{
playerPos[1 - pNumber] -= 6;
Console.WriteLine("玩家{0}选择轰炸玩家{1},玩家{2}退6格", playerName[pNumber], playerName[1 - pNumber], playerName[1 - pNumber]);
replace();
break;
}
else if (str == "2")
{
int temp = playerPos[1 - pNumber];
playerPos[1 - pNumber] = playerPos[pNumber];
playerPos[pNumber] = temp;
break;
}
else
{
Console.WriteLine("请输入1或2!!!");
str = Console.ReadLine();
}
}
Console.ReadKey(true);
break;
case 2://地雷
Console.WriteLine($"玩家{playerName[pNumber]}踩到了地雷,退6格");
playerPos[pNumber] -= 6;
replace();
Console.ReadKey(true);
break;
case 3://暂停
Console.WriteLine($"玩家{playerName[pNumber]}踩到了暂停,暂停一回合");
playerState[pNumber] = true;
Console.ReadKey(true);
break;
case 4://时空隧道
Console.WriteLine($"玩家{playerName[pNumber]}进入时空隧道,前进10格");
playerPos[pNumber] += 10;
Console.ReadKey(true);
replace();
break;
}

Console.ReadKey(true);
replace();
Console.Clear();
}

public static void Win()
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(" ◆ ");
Console.WriteLine(" ■ ◆ ■ ■");
Console.WriteLine(" ■■■■ ■ ■ ◆■ ■ ■ ■");
Console.WriteLine(" ■ ■ ■ ■ ◆ ■ ■ ■ ■");
Console.WriteLine(" ■ ■ ■■■■■■ ■■■■■■■ ■ ■ ■");
Console.WriteLine(" ■■■■ ■ ■ ●■● ■ ■ ■");
Console.WriteLine(" ■ ■ ■ ● ■ ● ■ ■ ■");
Console.WriteLine(" ■ ■ ■■■■■■ ● ■ ● ■ ■ ■");
Console.WriteLine(" ■■■■ ■ ● ■ ■ ■ ■ ■");
Console.WriteLine(" ■ ■ ■ ■ ■ ■ ■ ■");
Console.WriteLine(" ■ ■ ■ ■ ■ ■ ");
Console.WriteLine(" ■ ■ ■ ■ ● ■ ");
Console.WriteLine(" ■ ■■ ■■■■■■ ■ ● ●");
Console.ResetColor();
}

static void replace()
{
if (playerPos[0] <= 0) playerPos[0] = 0;
else if (playerPos[0] >= 99) playerPos[0] = 99;

if (playerPos[1] <= 0) playerPos[1] = 0;
else if (playerPos[1] >= 99) playerPos[1] = 99;
}
}
}

#Day7 2024.04.24

这节课开始学习面向对象编程

类,对象(实例)的概念和使用

类:是一个模具,确定了对象将要拥有的【特征】和【行为】

对象可以叫做类的实例

  • 比如:电脑是类,拥有一块屏幕、一块主板、一块键盘等特征,可以敲代码、打游戏等行为的物品,统称为电脑。

    我现在手里这个物品就是电脑(因为它具有电脑的特征),只有我手中的这台电脑才能称为对象,是一个实例。

在编程中,我们称 特征 为【属性】,行为 为【方法】

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
static void Main(string[] args)
{
//1、创建对象
//类名 对象名 = new 类名();
person kk = new person();//创建了一个名为kk的person类的对象(实例)


//2、给对象初始化
//有三种方法
//2.1初始化的第一种方式:普通赋值法

kk._name = "kk";
kk._age = 18;
kk._gender = '男';
kk.Chinese = 100;//字段和属性
kk._math = 100;
kk._enlish = 100;

//2.2初始化的第二种方式:调用对象的【构造函数】,为对象进行初始化

Person kk = new Person("kk",18,'男',100,100,100);
//如果遇到【构造函数】重载(Line46),则在需要的数据上填入初始值
//例如
//Person kk = new Person(null,0,'\0',100,100,100);

//2.3初始化的第三种方式:对象初始化器
//我需要new一个对象,但是我只需要某些值并且懒得看顺序,用初始化器就非常方便
Person kk = new Person() {name = "kkk",gender = '男',chinese = 89}


//3、执行对象的行为(调用对象的方法)
kk.SayHello();
}
//为了看得方便,就在这儿写person类

class Person//类的后面不用加括号
{
public string Name { get:set;}
public int Age { get:set;}
public char Gender { get:set;}

//public int chinese { get:set;}
private int _chinese;//字段变量前面加_
public int Chinese
{
get//get在打印的时候赋值。比如,Console.ReadLine();调用get.只有在打印的时候需要判断数据是否合理
{
if(_chinese < 0 || _chinese > 100) {
_chinese = 80;

}
return _chinese;
}
set//set在赋值的时候调用。因此我只需要接受就好了,等到打印的时候如果不合理再进行判断
{
_chinese = value;
}
}


public int Math { get:set;}
public int English { get:set;}

private int _height = 179;
private int _weight = 179;
private static int _music =80;
private static int _tiYu = 90;//41-44行代码是为了说明,静态变量比非静态变量先生成,静态类同理比普通类先生成

public Person(string name, int age, char gender, int chinese, int math, int english)
{
this.Name = name;
this.Age = age;
this.Gender = gender;
this.Chinese = chinese;
this.Math = math;
this.English = english;
}
//让自己的构造函数,调用自己的构造函数,使用关键字 this
//this:1、表示当前类的对象 2、显示的调用本类的构造函数
public Person(string name, int age, char gender) : this(name, age, gender, 0, 0, 0)
{
//this.Name = name;
//this.Age = age;
//this.Gender = gender;
}
public Person(int chinese, int math, int english):this(null,0,'\0',chinese,math,english)
{
//this.Chinese = chinese;
//this.Math = math;
//this.English = english;
}

public Person()
{

}
//构造函数,本质上就是第一个【特殊】的函数
//1、方法名跟类名一样
//2、没有返回值,连void也不能写
//3、new对象的时候,会自动的调用构造函数
//4、每一个类,都会有一个默认无参数的构造函数,当你写了一个新的之后,那个默认的无参数的就被干掉了
//5、构造函数是可以重载的
//默认有一个代码里面看不见,但是编译器会给我们添加上的一个无参数的构造函数


public void SayHello(){
Console.WriteLine("大家好,我是{0},我今年{1}岁,我是{2}生",_name,_age,_gender);
}

}

静态和实例的区别以及应用场景

静态:属于类

使用方法:类名.方法名() 比如:Console.ReadLine(); Convert.ToInt32();

1、调用的时候,静态成员必须使用类名标记
2、静态的加载,先于实例成员的加载
3、静态类不允许创建对象,静态类中不能出现实例成员,只能是静态成员,实例成员属于对象。
4、静态类应该少用,因为占用内存
5、【静态类】在编程中一般作为【工具类】来使用。 Console
6、【静态成员】在整个程序运行的过程中,静态资源都不会被释放,只有程序关闭的时候,静态资源才会被释放

实例:属于对象

  • 可以这样理解:类是对象的模板或者蓝图,而实例或者对象则是根据这个模板或蓝图创建出来的具体实体。换句话说,对象是一个抽象的概念,而实例则是这个概念的具体化。所以说,说实例属于对象是正确的,因为实例是对象的一种具体表现形式。

1、调用实例成员的时候,需要使用 对象.实例成员 的方式调用 yaoYao.SayHello();
2、普通类中,既可以有静态成员,也可以有非静态成员,因为静态成员属于类

几个非常重要的知识点

  1. 静态方法中,只能使用静态成员,因为使用静态方法的时候不一定有实例对象。
  2. 实例方法中,静态成员和实例成员都可以使用
  3. 静态类必须全是静态成员
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
51
52
53
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace _07_静态和非静态
{
internal class Program
{
static void Main(string[] args)
{
Person.SayHello();
Console.ReadKey();
}
}

public class Person //internal:只能在当前项目的内部访问======================
{
public static string _name;
public static string _pwd;
private char _gender;
public static void SayHello()
{
//静态方法中,只能使用静态成员,因为有静态方法的时候,不一定有实例对象,因此无法访问实例对象(_gender)
///////////////////////////////
Driver driver = new Driver();//这是创建对象的代码,而不是用这个对象中的实例成员的代码,因此可以使用不报错
/////////////////////////////
Console.WriteLine();
}
public void SayHi()//实例方法才可以用this
{
Console.WriteLine(this._gender);
Console.WriteLine(_name);
Console.WriteLine(_pwd);
}
}

static class Teacher
{
//静态类必须全是静态成员
}

class Driver
{

}
}

命名空间的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _07_静态和非静态;////////////////////------
namespace _08_命名空间的使用
{
internal class Program
{
static void Main(string[] args)
{
//在一个项目中,引用另外一个项目的类
//1、添加引用(::::::::::::)
//2、确定要使用的类是public(===============)
//3、添加命名空间的引用(-------)
Person person = new Person();::::::::::::
}
}
}

值传递和引用传递

自己看代码理解,容易。干想不出来就画图。

#Day8 2024.04.26

字符串的操作

ToLower:得到字符串的小写形式

ToUpper:得到字符串的大写形式

用法:s = s.ToLower();

拓展:s1.Equals( s2, StringComparsion.OrdianlIgnoreCase) — bool类型

String[] Spilt(params char[] separator):将字符串按照指定的分隔符分割成字符串数组

String[] Spilt(char[] separrator, StringSpiltOptions options):options取RemoveEmptyEntries的时候移除结果中的空白字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//练习 从日期字符串("2008-08-08")中分析出年、月、日;2008年08月08日。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace pra
{
internal class Program
{
static void Main(string[] args)
{
string str = "2008-08-08";
string[] strings = str.Split(new char[] { '-' });
Console.WriteLine("{0}年{1}月{2}日", strings[0], strings[1], strings[2]);
Console.ReadKey();
}
}
}

string Replace(string lodValue, string newValue):将字符串中的出现oldValue的地方替换为newValue。例子:名字替换

string Substring(int startIndex):取从位置startIndex开始一直到最后的子字符串

string Substring(int startIndex, int length):取从位置startIndex开始长度为length的子字符串,如果子字符串的长度不足length则报错

*bool Contains(string value) :判断字符串中是否含有子串value

*bool StartWith(string value):判断否以子串value开始

*bool EndsWith(string value):判断字符字符串是串是否以子串value结束

*int IndexOf(string value):取子串value第一次出现的位置

int LastIndexof(string value) :取子串value最后一次出现的位置

Trim() 、TrimEnd()、TrimStart():同时去除两边的空格、去除后面的空格、去除前面的空格

IsNullOrEmpty() :判断字符串是否为空或不存在

*int IndexOf(string value, int startIndex) :获取从下标StartIndex后的第一个value的下标

字符串练习

1、接收用户输入的字符串,将其中的字符以与输入相反的顺序输出。”abc”→”cba”

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace pra
{
internal class Program
{
static void Main(string[] args)
{
pra1();
//
Console.ReadKey();
}

static void pra1()//Array.Reverse()
{
//接收用户输入的字符串,将其中的字符以与输入相反的顺序输出。"abc"→"cba"
string str = "abc";
char[] arr = str.ToCharArray();// 把字符串转化为char数组
Array.Reverse(arr);
string s = new string(arr);//把char数组转化为string类型
Console.WriteLine(s);
Console.ReadKey();
}
}
}

2、接收用户输入的一句英文,将其中的单词以反序输出。”hello c sharp”→”sharp c hello”

1
2
3
4
5
6
7
8
9
10
11
static void pra2()//str.Split()
{
//接收用户输入的一句英文,将其中的单词以反序输出。"hello c sharp"→"sharp c hello"
string str = "hello c sharp";
string[] ss = str.Split(new char[] {' '});
for(int i = ss.Length - 1; i >= 0; i--)
{
Console.Write(ss[i] + " ");
}
Console.ReadKey();
}

3、从Email中提取出用户名和域名:abc@163.com

1
2
3
4
5
6
7
8
9
10
static void pra3()str.INdexOf()   str.Substring()
{
//从Email中提取出用户名和域名:abc@163.com
string str = "abc@163.com";
int pos = str.IndexOf("@");
string userName = str.Substring(0, pos);
string YuMing = str.Substring(pos + 1);
Console.WriteLine("用户名是{0},域名是{1}",userName,YuMing);
Console.ReadKey();
}

4、文本文件中存储了多个文章标题、作者,标题和作者之间用若干空格(数量不定)隔开,每行一个,标题有的长有的短,输出到控制台的时候最多标题长度10,如果超过10,则截取长度8的子串并且最后添加“…”,加一个竖线后输出作者的名字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static void pra4()//File.ReadAllLine()  str.Split()
{
//文本文件中存储了多个文章标题、作者,标题和作者之间用若干空格(数量不定)隔开,每行一个,
//标题有的长有的短,输出到控制台的时候最多标题长度10,如果超过10,则截取长度8的子串并且最后添加“...”,
//加一个竖线后输出作者的名字。
string path = @"E:\C#project\C#BasicDay08\111.txt";

string[] str = File.ReadAllLines(path);

for(int i = 0;i < str.Length; i++)
{
string[] ss = str[i].Split(new char[] { '\t' },StringSplitOptions.RemoveEmptyEntries);
//如果只写new char[] { '\t' }则将原本的'\t'变成""
if (ss[0].Length > 10)
{
ss[0] = ss[0].Substring(0, 8);
ss[0] += "...";
}
Console.WriteLine("{0}|{1}", ss[0], ss[1]);
}

Console.ReadKey();
}

5 、让用户输入一句话,找出所有e的位置

1
2
3
4
5
6
7
8
9
10
11
static void pra5()//str.IndexOf()
{
string str = "eerasomdeionasededneneinlenbn";
int index = str.IndexOf("e");

while(index != -1)
{
Console.WriteLine("{0} ",index);
index = str.IndexOf("e",index + 1);
}
}

6、让用户输入一句话,判断这句话中有没有邪恶,如果有邪恶就替换成这种形式然后输出,如:老牛很邪恶,输出后变成老牛很**;

1
2
3
4
5
6
7
8
9
10
static void pra6()//str.Replace()
{
string str = "老牛很邪恶";

if(str.Contains("邪恶"))
{
str = str.Replace("邪恶", "****");
}
Console.WriteLine(str);
}

7、把{“诸葛亮”,”鸟叔”,”卡卡西”,”卡哇伊”}变成诸葛亮|鸟叔|卡卡西|卡哇伊,然后再把|切割掉

1
2
3
4
5
6
7
8
9
10
11
static void pra7()//string.Join()
{
string[] str = new string[] { "诸葛亮", "鸟叔", "卡卡西", "卡哇伊" };
string s = String.Join("|",str);
string[] ss = s.Split(new char[] { '|' },StringSplitOptions.RemoveEmptyEntries);
for(int i = 0; i < ss.Length; i++)
{
Console.WriteLine(ss[i]);
}
Console.ReadKey();
}

继承

继承存在的目的:

1、减少子类中的冗余代码

2、让类与类之间产生的关系,为后续的多态打下了基础。

概念:

把同一物种下的类,中的冗余成员,封装到一个类中。这个类作为其他的父类(基类),其他类是这个类的子类(派生类)

语法:

子类:父类

特性:

1、单根性:一个类只能有一个父类.

object:是一切数据类型的父类
如果一个类,没有继承任何类,那么这个类就继承object
如果一个类,继承了别的类,那么这个类隐式的也继承了object

2、传递性:破坏类的密封性

base和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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _08_继承的构造函数问题
{
internal class Program
{
static void Main(string[] args)
{
//继承中的构造函数问题
//Person:父类
//Student 、Teacher、Driver:子类
//我们在创建子类对象的时候,会先去调用父类的默认无参的构造函数,然后再执行子类自己的构造函数。
//为什么?
//1、本质上,还是为了解决冗余代码的问题(给属性赋值的冗余代码)
//2、子类在创建对象之前,有些属性的值,是确定的。(相同的),这些值,如果是从父类那继承过来的,那么就可以在父 类的构造函数
//中,对他们进行初始化,这样就减少了子类属性赋值的冗余代码
//3、子类要用父类属性的值。
//解决方案:
//1、在父类中,补充一个无参数的构造函数
***** //2、让子类,不去调用父类无参数的构造函数,而是调用父类有参数的构造函数,通过关键字:base
Student s = new Student("张三",18,'男',100);

//本质上,子类继承了父类的私有成员,但是由于private的原因,子类调用不到父类的私有成员,所以,我们认为子类没 有继承父类的私有成员。
//子类继承了父类的哪些成员?
//属性继承了
//方法继承了
//构造函数:子类没有继承父类的构造函数,调用父类的构造函数。
//字段有没有继承?继承了但是用不了

//4、访问修饰符:proctected,受保护的,只能在当前类的内部,以及该类的子类中访问
Console.ReadKey();
}
}

class ChinesePerson
{
//private int _chiense;
protected int _chinese;
public string Name { get; set; }

public int Age { get; set; }

public char Gender { get; set; }

public string Country { get; set; }

public ChinesePerson(string name, int age, char gender)
{
this.Name = name;
this.Age = age;
this.Gender = gender;
}
//先执行父类的构造函数再执行子类的构造函数(为了解决冗余代码的问题,或者用人话说就是子类要用父类属性的值)
public ChinesePerson()
{
this.Country = "中国";
}//父类的构造函数中初始化了Country因此每个子类都有Country

public void CHLSS()
{
Console.WriteLine("人类可以吃喝拉撒睡");
}
}

class Student : ChinesePerson
{
public int ID { get; set; }


public Student(string name, int age, char gender, int id) : base(name, age, gender)
{
this.ID = id;
}

public void Study()
{
int Age = 19;
Console.WriteLine(base.Age); ////
}
}

class Teacher : ChinesePerson
{

public Teacher(string name, int age, char gender, double workYear) : base(name, age, gender)
{
this.WorkYear = workYear;
}

public double WorkYear { get; set; }

public void Teach()
{
Console.WriteLine("老师会讲课");
}
}

class Driver : ChinesePerson
{
public Driver(string name, int age, char gender, int driveYear) : base(name, age, gender)
{
this.DriverYear = driverYear;
}

public int DriveYear { get; set; }
public void Drive()
{
Console.WriteLine("司机要会开车");
}
}
}

里式替换原则

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
51
52
53
54
55
56
57
58
59
60
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 里式替换原则
{
internal class Program
{
static void Main(string[] args)
{
Person p = new Student();//创建Person类,但是指向新建的Student内存空间.为了程序的可扩展。
p.SayHi();

//由父类转子类的方法有is和as两种
//is
if(p is Student)
{
Console.WriteLine("转变成功");
}
else
{
Console.WriteLine("转变失败");
}
//as
Student s = p as Student;
if (s != null)
{
Console.WriteLine("转变成功");
}
else
{
Console.WriteLine("转变失败");
}
Console.ReadKey ();
}
}

class Person
{
public void SayHi()
{
Console.WriteLine("我是父类");
}
}

class Student : Person
{
public void SayHi()
{
Console.WriteLine("我是子类");
}
}
class Teacher : Person
{

}
}

里式转换案例

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _10_里式转换案例
{
internal class Program
{
static void Main(string[] args)
{
//声明一个数组:Person、Student、Teacher、Driver、Programmer
Person[] pers = { new Person(), new Student(), new Teacher(), new Driver(), new Programmer() };

for (int i = 0; i < pers.Length; i++)
{

//pers[i].SayHi();


if (pers[i] is Programmer)
{
Programmer p = (Programmer)pers[i];
p.SayHi();
}
else if (pers[i] is Student)
{
Student s = (Student)pers[i];
s.SayHi();
}
else if (pers[i] is Teacher)
{
Teacher t = (Teacher)pers[i];
t.SayHi();
}
else if (pers[i] is Driver)
{
Driver d = (Driver)pers[i];
d.SayHi();
}
else if (pers[i] is Person)
{
pers[i].SayHi();
}

}
Console.ReadKey();
}
}

class Person
{
public void SayHi()
{
Console.WriteLine("我是人类");
}
}

class Student : Person
{
public void SayHi()
{
Console.WriteLine("我是学生");
}
}

class Teacher : Person
{
public void SayHi()
{
Console.WriteLine("我是老师");
}
}

class Programmer : Person
{
public void SayHi()
{
Console.WriteLine("我是程序员");
}
}
class Driver : Person
{
public void SayHi()
{
Console.WriteLine("我是司机");
}
}
}

#Day9 2024.04.27

集合

非泛型集合ArrayListHashTable—这两个用的少,因为涉及到拆箱装箱问题影响效率。

泛型集合List<T>Dictionary<Tkey,Tvalue>—因为这两个不涉及拆箱装箱问题,效率高,所以用的多

拆箱:值类型 ——> 引用类型

装箱:引用类型—— >值类型

从数组到集合是因为集合长度可变而且使用更加灵活

泛型集合练习

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace test
{
internal class Program
{
static void Main(string[] args)
{
pra6();
Console.ReadKey();
}

static void pra1()
{
//有一个整数数组{1,2,3,4,5,6,7,8,9},将奇数取出来放到前面,偶数放到后面,
//最终将两个集合合并为1个集合,要求奇数在前面,偶数在后面。

List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<int> odds = new List<int>();
List<int> even = new List<int>();

foreach (int i in list)
{
if(i % 2 == 1) odds.Add(i);
else even.Add(i);
}
odds.AddRange(even);

//Console.WriteLine(odds);
foreach (int i in odds)
{
Console.WriteLine(i);
}
}

static void pra2()
{
//有两个集合:{a,b,c,e,f,g} {e,f,g,h,i,j,k}将两个集合,合并为1个集合,要求没有重复项。
List<char> chars1 = new List<char>() { 'a', 'b', 'c', 'd', 'f', 'g' };
List<char> chars2 = new List<char>() { 'e', 'f', 'g', 'h', 'i', 'j', 'k' };

foreach (char c in chars2)
{
if(chars1.Contains(c))
{
chars1.Remove(c);
}
}
chars1.AddRange(chars2);
foreach (char c in chars1)
{
Console.WriteLine(c);
}
}

static void pra3()
{
//统计welcome to china中每个字符出现的次数 字母X出现了X次
string str = "welcome to china";

char[] chars = str.ToCharArray();
Dictionary<char ,int> ci = new Dictionary<char ,int>();

for (int i = 0; i < chars.Length; i++)
{
try
{
if (chars[i] != ' ')
{
ci[chars[i]] += 1;
}
}
catch
{
ci.Add(chars[i], 1);
}
}
foreach(var item in ci)
{
Console.WriteLine("{0}字母出现了{1}次", item.Key,item.Value);
}
}

static void pra4()//
{
//有一个字符串”1一 2二 3三 4四 5五 6六 7七 8八 9九”,提示用户阿拉伯数字,返回大写。
string str = "1一 2二 3三 4四 5五 6六 7七 8八 9九";
char[] chars = str.ToCharArray();
Dictionary<char,char> CCP = new Dictionary<char,char>();
string[] lines = str.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);

foreach(var item in lines)
{
CCP.Add(item[0], item[1]);
}

Console.WriteLine("请输入阿拉伯数字");
string s = Console.ReadLine();

for(int i = 0; i < s.Length; i++)
{
if (CCP.ContainsKey(s[i]))
{
Console.Write(CCP[s[i]]);
}
else
{
Console.Write(s[i]);
}
}

//Console.ReadKey();
}

static void pra5()
{
//提示用户输入一个字符串,使用foreach循环将字符串中每一个字符赋值给一个char数组。
Console.WriteLine("输入一个字符串");
string str = Console.ReadLine();
char[] chars = new char[110] ;
int i = 0;
foreach (var item in str)
{
chars[i++] = (char)item;
}
Console.WriteLine(chars);
}

static void pra6()//
{
//不停的提示用户输入名字,输入end的时候,显示刚才所有的名字。
//并且告诉用户这其中有多少姓王的同学。
int count = 0;
List<string> names = new List<string>();
while(true)
{
Console.WriteLine("请输入名字");
string s = Console.ReadLine();
if(s == "end")
{
break;
}
names.Add(s);
char[] sr = s.ToCharArray();
if (sr[0] == '王')
{
count++;
}
}
foreach (var item in names)
{
Console.WriteLine(item);
}
Console.WriteLine(count);

}
}
}

FILE

Flie.Create(path)

File.Delite(path)

File.Exists(path)

File.Copy(Source path,destnation path)

File.Move(Source path,destnation path)

读取数据

File.ReadAllText(path)

File.ReadAllLines(path)

File.ReadAllBytes(path)

写入数据

File.WriteAllText(path)

File.WriteAllLines(path)

File.WriteAllBytes(path)

字符串到字节数组

Encoding.Default.GetBytes(string s)

Encoding.Default.GetString(byte[] buffer)

1
2
3
4
string s1 = @"c:\a\b\c\";
string s2 = @"111.avi";

string s3 = Path.Combine(s1, s2);//智能检测到s1最后的\,如果有就不加,没有就加

Path

path.GetFileName():path.GetFileName() 是一个 System.IO 类中的方法,用于从文件路径中获取文件名(包括文件扩展名)。例如:

1
2
3
string filePath = "C:\\Users\\User\\Documents\\file.txt";
string fileName = Path.GetFileName(filePath);
Console.WriteLine(fileName); // 输出: file.txt

path.GetFileNameWithoutExtension():path.GetFileNameWithoutExtension() 是另一个 System.IO 类中的方法,用于从文件路径中获取不包含文件扩展名的文件名。例如:

1
2
3
string filePath = "C:\\Users\\User\\Documents\\file.txt";
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath);
Console.WriteLine(fileNameWithoutExtension); // 输出:file

path.Combine():path. Combine() 方法用于将多个字符串路径组合为一个有效的路径。它自动处理斜杠和反斜杠,以及路径之间的冗余问题。例如:

1
2
3
4
string directoryPath = "C:\\Users\\User\\Documents";
string fileName = "file.txt";
string filePath = Path.Combine(directoryPath, fileName);
Console.WriteLine(filePath); // 输出: C:\\Users\\User\\Documents\\file.txt

Directory

Directory.CreateDirectory():是一个 System.IO 类中的方法,用于创建一个新的目录。如果指定的目录已经存在,该方法不会进行任何操作。例如:

1
2
string directoryPath = "C:\\Users\\User\\Documents\\NewFolder";
Directory.CreateDirectory(directoryPath); // 创建名为 "NewFolder" 的目录

Directory.Delete():用于删除指定的目录以及其中的所有文件和子目录。注意,删除操作是递归的,即会删除目录及其子目录和文件。需要谨慎使用,并确保备份重要文件。例如:

1
2
string directoryPath = "C:\\Users\\User\\Documents\\NewFolder";
Directory.Delete(directoryPath, true); // 删除名为 "NewFolder" 的目录及其所有内容

Directory.Move():用于移动目录或重命名目录。可以将目录移动到新位置,或者只更改目录的名称。例如

1
2
3
string sourceDirectoryPath = "C:\\Users\\User\\Documents\\SourceFolder";
string destinationDirectoryPath = "C:\\Users\\User\\Documents\\DestinationFolder";
Directory.Move(sourceDirectoryPath, destinationDirectoryPath); // 将名为 "SourceFolder" 的目录移动到 "DestinationFolder" 目录位置

Directory.GetFiles():用于获取指定目录中的所有文件的路径。可以选择搜索所有子目录或只搜索当前目录。例如:

1
2
3
4
5
6
string directoryPath = "C:\\Users\\User\\Documents";
string[] files = Directory.GetFiles(directoryPath, "*.*", SearchOption.AllDirectories);
foreach (string file in files)
{
Console.WriteLine(file); // 输出目录中的所有文件路径
}

Directory.GetDirectories:用于获取指定目录中的所有子目录的路径。可以选择搜索所有子目录或只搜索当前目录。例如:

1
2
3
4
5
6
string directoryPath = "C:\\Users\\User\\Documents";
string[] directories = Directory.GetDirectories(directoryPath, "*", SearchOption.AllDirectories);
foreach (string directory in directories)
{
Console.WriteLine(directory); // 输出目录中的所有子目录路径
}

多态

当父类有具体实现方法时用虚方法,无具体实现方法时用抽象类。

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//虚拟类重写
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _12_里式转换案例重写
{
internal class Program
{
static void Main(string[] args)
{
//声明一个数组:Person、Student、Teacher、Driver、Programmer
Person[] pers = { new Person(), new Student(), new Teacher(), new Driver(), new Programmer() };

for (int i = 0; i < pers.Length; i++)
{
pers[i].SayHi();
}
Console.ReadKey();
}
}

class Person
{
public virtual void SayHi()
{
Console.WriteLine("我是人类");
}
}

class Student : Person
{
public override void SayHi()
{
Console.WriteLine("我是学生");
}
}

class Teacher : Person
{
public override void SayHi()
{
Console.WriteLine("我是老师");
}
}

class Programmer : Person
{
public override void SayHi()
{
Console.WriteLine("我是程序员");
}
}
class Driver : Person
{
public override void SayHi()
{
Console.WriteLine("我是司机");
}
}

}
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//抽象类重写
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _15_抽象类
{
internal class Program
{
static void Main(string[] args)
{
//动物会叫,猫会喵喵叫,狗会叫汪汪叫,鸟会唧唧叫

//计算圆形、矩形、三角形的面积

//不允许创建抽象类的实例对象
//Animal a = new Cat();
//a.Bark();
//Animal[] animals = { new Cat(), new Dog(), new Bird() };
//for (int i = 0; i < animals.Length; i++)
//{
// animals[i].Bark();
//}

Shape shape = new Rec(5, 10);// new Circle(5);
double area = shape.GetArea();
Console.WriteLine(area);

Console.ReadKey();

}
}


abstract class Shape
{
public abstract double GetArea();
}

class Circle : Shape
{
public double R { get; set; }
public Circle(double r)
{
this.R = r;
}
public override double GetArea()
{
return Math.PI * this.R * this.R;
}
}

class Rec : Shape
{
public double Height { get; set; }
public double Width { get; set; }
public Rec(double height, double width)
{
this.Height = height;
this.Width = width;
}

public override double GetArea()
{
return this.Height * this.Width;
}
}

//如果一个普通类中出现了抽象成员,那么这个类也必须被标记为抽象的
abstract class Animal
{
//抽象方法不允许有方法体
public abstract void Bark();

}

//子类如果继承了一个抽象父类,那么子类必须重写抽象父类中的所有抽象成员
class Cat : Animal
{
public override void Bark()
{
Console.WriteLine("猫咪喵喵叫");
}
}
class Dog : Animal
{
public override void Bark()
{
Console.WriteLine("狗狗汪汪叫");
}
}
class Bird : Animal
{
public override void Bark()
{
Console.WriteLine("鸟唧唧叫");
}
}
}

#Day10 2024.04.28

单例设计模式

先导概念:如果我想对我家装修,装修风格是叙利亚战损风。

战损风要求:

  1. 墙体的颜色以黑色。灰色交叉为主。
  2. 地板装以破碎拼接为主
  3. 窗户以裂纹为主
  4. 。。。。。

设计模式:解决的是某个场景下的固定/单一问题。

重点问题:如何使得在整个程序中只有唯一的对象?//应用场景:手机APP只能打开一个

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
51
52
53
54
55
56
57
58
59
//重点解决如何只创建一个对象的问题
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 单例设计模式
{
internal class Program
{
static void Main(string[] args)
{
//如果想要实现单例设计模式就是让外界只有第一次调构造函数的时候才会调到(也就是说只有第一次创建对象才会创建一个人新的对象)
//而创建对象则是如下流程1、在内存中开辟空间。2、在开辟的内存空间中心创建对象。3、调用对象的构造函数进行对象的初始化。
//STEP1和STEP2中无法人为去操控。因此人为进行STEP3就可以创建对象。
Person p1 = Person.GetSinglePerson();//静态方法使用.。实例方法用new
Person p2 = Person.GetSinglePerson();

int h1 = p1.GetHashCode();
int h2 = p2.GetHashCode();

Console.WriteLine(h1);
Console.WriteLine(h2);//一样就说明全局只有一个Person对象

Console.ReadKey();
}
}

class Person
{
//1、构造函数私有化
private Person()//保证外面不能new一个Person
{

}
////2、声明一个【静态】字段,用来存储全局唯一的Person对象
//private static Person _singlePerson = null;//懒汉设计模式(不安全

////3、在类中,声明一个静态方法,用来返回这个类全局唯一的Person对象
//public static Person GetSinglePerson()
//{
// if(_singlePerson == null )
// {
// _singlePerson = new Person();
// }
// return _singlePerson;
//}

private static Person _singlePerson = new Person();//饿汉设计模式(更安全

public static Person GetSinglePerson()
{
return _singlePerson;
}


}
}

工厂设计模式

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 简单工厂设计模式
{
internal class Program
{
static void Main(string[] args)
{
//简单工厂设计模式
//根据用户的需求,生产符合用户的产品对象
//生产笔记本
//1、把父类找出来
//2、确定子类
//3、继承的成员
//4、是否要实现多态
Console.WriteLine("你要什么类型的笔记本");
string Brand = Console.ReadLine();

Computer cpu = GetComputer(Brand);
cpu.ShowBrand();

Console.ReadKey();

}

static Computer GetComputer(string Brand)
{
Computer cpu = null;
switch (Brand)
{
case "Lenovo":
cpu = new Lenovo();
break;
case "HP":
cpu = new HP();
break;
case "Dell":
cpu = new Dell();
break;
case "Acer":
cpu = new Acer();
break;
}
return cpu;
}

}
/// <summary>
/// 笔记本父类
/// </summary>
abstract class Computer
{
public abstract void ShowBrand();
}

class Lenovo : Computer
{
public override void ShowBrand()
{
Console.WriteLine("Lenovo");
}
}

class Dell : Computer
{
public override void ShowBrand()
{
Console.WriteLine("Dell");
}
}

class HP : Computer
{
public override void ShowBrand()
{
Console.WriteLine("HP");
}
}

class Acer : Computer
{
public override void ShowBrand()
{
Console.WriteLine("Acer");
}
}
}

超市收银系统


业务流程怎么安排?

  • 一整个业务流程包含多个方面

因此首先要分出类的种类以及每个种类需要完成什么功能

本超市收银系统主要分为如下几个大类

  1. 产品类
  2. 折扣类
  3. 仓库类
  4. 超市类(前台交互类)

点击运行超市收银系统(仅限本地)

接口

接口:不是所有子类都具备某一个能力,或者跨物种的实现多态。考虑使用接口。(更为简单的抽象类)

​ 1、表示一种能力

​ 2、表示一种规范(高级课再讲

人话:不是所有鸟类都会飞,因此创建一个IFlyable接口给能飞的鸟类使用。

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
51
52
53
54
55
56
57
58
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 接口
{
internal class Program
{
static void Main(string[] args)
{
Sparrow bird = new Sparrow();
bird.Singing();
bird.Fly();
Console.ReadKey();
}
}

interface IFlyable { void Fly(); }

abstract class Bird
{
public abstract void Singing();
}

class Sparrow:Bird,IFlyable
{
public override void Singing()
{
Console.WriteLine("我是麻雀我会麻雀叫");
}
public void Fly()
{
Console.WriteLine("我是麻雀我会飞");
}
}

class Penguin:Bird
{
public override void Singing()
{
Console.WriteLine("我是企鹅我会企鹅叫");
}
}

class Parrot:Bird, IFlyable
{
public override void Singing()
{
Console.WriteLine("我是鹦鹉我会鹦鹉叫");
}
public void Fly()
{
Console.WriteLine("我会飞");
}
}
}

依赖注入


依赖注入简单来说就是A类要使用B类的某一些方法,B类被注入到A类中,A类就可以使用该方法了。

A依赖B,B注入A。

For Instance

把移动硬盘、U盘、MP3插到电脑上使用。

  1. 属性注入
  2. 构造函数注入
  3. 方法注入
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 依赖注入
{
internal class Program
{
static void Main(string[] args)
{
//把移动硬盘、U盘、MP3插到电脑上,读写数据
//父类:存储设备
//子类:移动硬盘、U盘、MP3

//1
//Computer cpu = new Computer();
//cpu.MSD = new USBFlushDrive();
//cpu.MSD.Read();
//cpu.MSD.Write();
//2
//ExternalHardDrive EHD = new ExternalHardDrive();
//Computer cpu = new Computer(EHD);
//cpu.MSD.Write();
//cpu.MSD.Read();

//3
MP3 mp3 = new MP3();
Computer cpu = new Computer();
cpu.ReadData(mp3);
cpu.WriteData(mp3);
mp3.playMusic();
Console.ReadKey();
}
}

interface IPlayMusic { void playMusic(); };

class Computer
{
//我需要使用这些储存设备进行读写操作就首先得插到电脑上

//1、属性注入
//public MobileStorageDevice MSD { get; set; }
//public void ReadData()
//{
// this.MSD.Read();
//}
//public void WriteData()
//{
// this.MSD.Write();
//}

//2、构造函数注入

//public MobileStorageDevice MSD;
//public void ReadData()
//{
// this.MSD.Read();
//}
//public void WriteData()
//{
// this.MSD.Write();
//}
//public Computer(MobileStorageDevice MSB)
//{
// this.MSD = MSB;
//}

//3、方法注入
public void ReadData(MobileStorageDevice MSB)
{
MSB.Read();
}
public void WriteData(MobileStorageDevice MSB)
{
MSB.Write();
}


}
abstract class MobileStorageDevice
{
public abstract void Write();
public abstract void Read();
}

class ExternalHardDrive:MobileStorageDevice
{
public override void Write()
{
Console.WriteLine("我是移动硬盘我能写数据");
}
public override void Read()
{
Console.WriteLine("我是移动硬盘我会读数据");
}
}

class USBFlushDrive : MobileStorageDevice
{
public override void Write()
{
Console.WriteLine("我是U盘我会写数据");
}
public override void Read()
{
Console.WriteLine("我是U盘我会读数据");
}

}

class MP3 : MobileStorageDevice, IPlayMusic
{
public override void Read()
{
Console.WriteLine("我是MP3我会读数据");
}
public override void Write()
{
Console.WriteLine("我是MP3我会写数据");
}

public void playMusic()
{
Console.WriteLine("我是MP3,我还会播放音乐");
}
}
}

#Day11 2024.04.30

FileStream文件流

File类是一次性复制,因此对CPU和内存的压力很大。能应用的文件大小不超过两个G。

因此FileStream文件流应运而生,其原理是在内存中创建一个的大约几Mb的空间作为缓冲区,分很多次对文件进行处理。

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
51
52
53
54
//使用FileStream文件流读写数据
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FileStream文件流
{
internal class Program
{
static void Main(string[] args)
{
//1、使用文件流首先要确定对象文件路径
string path = @"C:\Users\86159\Desktop\作弊码.txt";
//2、创建文件流对象
//2.1、参数一:文件路径
//2.2、FileMode:要对文件操作的方式
//2.3、FileAccess:要对文件数据操作的方式
//FileStream fsRead = new FileStream(path,FileMode.Open,FileAccess.Read);
////3、设置缓冲区存放文件(fragment)
//byte[] buffer = new byte[1024 * 1024];
////r:表示本次读取,实际读取到的有效字节数
////r为0则读完了
//int r = fsRead.Read(buffer, 0, buffer.Length);
////将buffer字节数组转化成字符串
//string s = Encoding.UTF8.GetString(buffer, 0, r);

//Console.WriteLine(s);
//Console.WriteLine("读取成功");
////GC不会主动回收缓冲区,需要手动回收
//fsRead.Flush();//清空缓冲区
//fsRead.Close();//关闭文件流
//fsRead.Dispose();//释放流所占用的资源,这三步一般使用Using代替


using(FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read)){
byte[] buffer = new byte[1024 * 1024];
//r:表示本次读取,实际读取到的有效字节数
//r为0则读完了
int r = fsRead.Read(buffer, 0, buffer.Length);
//将buffer字节数组转化成字符串
string s = Encoding.UTF8.GetString(buffer, 0, r);

Console.WriteLine(s);
Console.WriteLine("读取成功");
}


Console.ReadKey ();
}
}
}

StreamReader和StreamWriter

StreamReader和StreamWriter操作文本文件的读取流和写入流
File:一次性的读写
FileStream:文件流
StreamReader 一行一行的读取文本文件的数据

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
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StreamReaderStreamWriter
{
internal class Program
{
static void Main(string[] args)
{
string path = @"C:\Users\86159\Desktop\作弊码.txt";
using (StreamReader sr = new StreamReader(path))
{
while(!sr.EndOfStream)
{
//string line = sr.ReadLine();
//Console.WriteLine(line);
Console.WriteLine(sr.ReadLine());
}
}
Console.ReadKey();
}
}
}

窗体应用程序

后台:写逻辑用。
前台:展示,跟用户进行交互。
Designer.cs:初始化擦黄体控件,一般不用程序员参与。
Resx:资源文件。

窗体应用程序的编程思想:基于【事件】编程。

事件的触发、事件的注册、事件的响应。

一个控件可以有无数个事件

#Day12 2024.05.04

今日小结:

今天学了

  1. Combo下拉框
  2. Timer组件
  3. 如何生成验证码
  4. 简单的窗体小程序(首次使用了面向对象)
  5. 综合小程序(小坦克移动)

#Day13 2024.05.05

今日小结:

今天学了

  1. 线程
  2. C/S(套接字)

  1. 线程的用法

    使用Thread对象

    Thread th = new Thread(方法);

    th.IsBackground = true置于后台

    th.start()运行方法

    防止系统假死:Control.CheckForIllegalCrossThreadCalls = false

  2. 套接字的使用

    TCP连接:Socket socket = new socket(AddressFamily.InternetWork, Socket.Stream, ProtocolType.Tcp)

    UDP连接:Socket socket = new socket(AddressFamily.Internetwork, Socket.Dgram, ProtocolType.Udp)

    IP地址获取:IPAdress ip = Ipaddress.Parse(字符串)

    网络终结点获取(IP和端口):IPEndPoint point = new IpEndPoint(ip, int.Parse(字符串))

    使用套接字对象

    Socket socket = new Socket(AddressFamily.InternetWork, Socket.Stream, ProtocolType.Tcp) 本案例使用TCP

    套接字主要用法:

    1. 用于服务器监听套接字,一般使用名称:socketWatch
      • 绑定网络终结点:socketWatch.Bind(写网络终结点)
      • 设置监听队列:socketwatch.Listen(写队列最大长度)
      • 监听成功以后创建用于通信的套接字:Socket SocketTransInfos = socketWatch.Accept()
    2. 用于服务器通信套接字,一般使用名称:socket
      • 给客户端发送信息(字节流):socket.Send(字节流数组)
      • 接收客户端信息(字节流):socket.Receive(字节流数组)
      • 获取与本套接字通信的客户端套接字的网络终结点信息:socketWithClient.ReomteEndPoint
      • 字符串转字节流数组:byte[] buffer = Encoding.UTF8.GetBytes(字符串)
      • TIPS: 接收字节流信息时使用int r = socketListen.Receive(buffer)r表示实际收到的有效字节数
    3. 用于客户端通信套接字:
      • 连接服务器:socket.Connect(point)
      • 接收来自服务器的信息(字节流):socket.Receive(buffer)
      • 给服务器发送信息(字节流):socket.Send(buffer)

C#Day14-15 2024.05.07-2024.05.08

基础班结课项目:飞机大战

本项目涵盖基础班所有知识,意在培养写项目时的机构分类意识,目的是完成高内聚低耦合的完整项目。


  1. 玩家飞机
    • 属性:横坐标、纵坐标、宽度、高度、方向、速度、生命值、图像
    • 行为:移动、开火、撞击、绘制
  2. 敌人飞机
    • 类型(type
    • 属性:横坐标、纵坐标、宽度、高度、方向、速度、生命值、图像
    • 行为:移动、开火、撞击、绘制
  3. 背景
  4. 玩家子弹
    • 属性:横坐标、纵坐标、宽度、长度、速度、伤害、图像
    • 行为:攻击敌人飞机、绘制
  5. 敌人子弹
    • 类型(type
    • 属性:横坐标、纵坐标、宽度、长度、速度、伤害、图像
    • 行为:攻击玩家飞机。绘制
  6. 碰撞检测
  7. ……