Initial commit: C# 学习笔记和示例代码
- Lesson 01-10: C# 基础语法 - WebView2: 集成示例 - notes/: 详细笔记
This commit is contained in:
commit
f604d53191
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
# .NET
|
||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
*.cache
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vs/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Rr]elease/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
|
||||||
|
# NuGet
|
||||||
|
packages/
|
||||||
|
*.nupkg
|
||||||
|
|
||||||
|
# WebView2
|
||||||
|
*.WebView2/
|
||||||
1
WebView2Demo
Submodule
1
WebView2Demo
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 1d85cb160f81d5a41125d348f97c01b2db0a09b4
|
||||||
10
lessons/Lesson02/Lesson02.csproj
Normal file
10
lessons/Lesson02/Lesson02.csproj
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
67
lessons/Lesson02/Program.cs
Normal file
67
lessons/Lesson02/Program.cs
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson02
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// ========== 变量 ==========
|
||||||
|
int age = 25;
|
||||||
|
double height = 175.5;
|
||||||
|
string name = "无言势字幕";
|
||||||
|
char grade = 'A';
|
||||||
|
bool isActive = true;
|
||||||
|
|
||||||
|
Console.WriteLine("=== 变量 ===");
|
||||||
|
Console.WriteLine($"姓名: {name}");
|
||||||
|
Console.WriteLine($"年龄: {age}");
|
||||||
|
Console.WriteLine($"身高: {height}cm");
|
||||||
|
Console.WriteLine($"等级: {grade}");
|
||||||
|
Console.WriteLine($"状态: {isActive}");
|
||||||
|
|
||||||
|
// ========== var 自动推断 ==========
|
||||||
|
Console.WriteLine("\n=== var 自动推断 ===");
|
||||||
|
var message = "这是 string 类型";
|
||||||
|
var number = 42; // 推断为 int
|
||||||
|
Console.WriteLine($"message 是: {message.GetType()}");
|
||||||
|
Console.WriteLine($"number 是: {number.GetType()}");
|
||||||
|
|
||||||
|
// ========== 常量 ==========
|
||||||
|
Console.WriteLine("\n=== 常量 ===");
|
||||||
|
const int MAX_RETRY = 3;
|
||||||
|
const string VERSION = "v1.0";
|
||||||
|
Console.WriteLine($"最大重试次数: {MAX_RETRY}");
|
||||||
|
Console.WriteLine($"版本: {VERSION}");
|
||||||
|
|
||||||
|
// ========== 类型转换 ==========
|
||||||
|
Console.WriteLine("\n=== 类型转换 ===");
|
||||||
|
int i = 10;
|
||||||
|
double d = i; // 隐式转换
|
||||||
|
Console.WriteLine($"int -> double: {d}");
|
||||||
|
|
||||||
|
double d2 = 3.14;
|
||||||
|
int i2 = (int)d2; // 显式转换
|
||||||
|
Console.WriteLine($"double -> int: {i2}");
|
||||||
|
|
||||||
|
string s = i.ToString();
|
||||||
|
Console.WriteLine($"int -> string: {s}");
|
||||||
|
|
||||||
|
int i3 = int.Parse("123");
|
||||||
|
Console.WriteLine($"string \"123\" -> int: {i3}");
|
||||||
|
|
||||||
|
// ========== 输入练习 ==========
|
||||||
|
Console.WriteLine("\n=== 输入练习 ===");
|
||||||
|
Console.Write("请输入你的名字: ");
|
||||||
|
string inputName = Console.ReadLine();
|
||||||
|
Console.Write($"你好, {inputName}! ");
|
||||||
|
|
||||||
|
Console.Write("请输入年龄: ");
|
||||||
|
string ageInput = Console.ReadLine();
|
||||||
|
int userAge = int.Parse(ageInput);
|
||||||
|
Console.WriteLine($"你 {userAge} 岁了");
|
||||||
|
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lessons/Lesson03/Lesson03.csproj
Normal file
10
lessons/Lesson03/Lesson03.csproj
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
96
lessons/Lesson03/Program.cs
Normal file
96
lessons/Lesson03/Program.cs
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson03
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// ========== if / else ==========
|
||||||
|
Console.WriteLine("=== if / else ===");
|
||||||
|
int score = 85;
|
||||||
|
|
||||||
|
if (score >= 90)
|
||||||
|
{
|
||||||
|
Console.WriteLine("优秀");
|
||||||
|
}
|
||||||
|
else if (score >= 60)
|
||||||
|
{
|
||||||
|
Console.WriteLine("及格");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("不及格");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 三元运算符
|
||||||
|
string result = score >= 60 ? "及格" : "不及格";
|
||||||
|
Console.WriteLine($"三元运算: {result}");
|
||||||
|
|
||||||
|
// ========== switch ==========
|
||||||
|
Console.WriteLine("\n=== switch ===");
|
||||||
|
int day = 3;
|
||||||
|
|
||||||
|
switch (day)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
Console.WriteLine("星期一");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Console.WriteLine("星期二");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
Console.WriteLine("星期三");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine("其他");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== for 循环 ==========
|
||||||
|
Console.WriteLine("\n=== for 循环 ===");
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"计数: {i}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== foreach ==========
|
||||||
|
Console.WriteLine("\n=== foreach 循环 ===");
|
||||||
|
string[] names = { "无言势", "VRChat", "字幕" };
|
||||||
|
|
||||||
|
foreach (string name in names)
|
||||||
|
{
|
||||||
|
Console.WriteLine(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== while 循环 ==========
|
||||||
|
Console.WriteLine("\n=== while 循环 ===");
|
||||||
|
int count = 0;
|
||||||
|
while (count < 3)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"while: {count}");
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== do while ==========
|
||||||
|
Console.WriteLine("\n=== do while ===");
|
||||||
|
int n = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Console.WriteLine($"do while: {n}");
|
||||||
|
n++;
|
||||||
|
} while (n < 3);
|
||||||
|
|
||||||
|
// ========== break 和 continue ==========
|
||||||
|
Console.WriteLine("\n=== break 和 continue ===");
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
if (i == 3) continue; // 跳过 3
|
||||||
|
if (i == 7) break; // 退出循环
|
||||||
|
Console.WriteLine(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lessons/Lesson04/Lesson04.csproj
Normal file
10
lessons/Lesson04/Lesson04.csproj
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
119
lessons/Lesson04/Program.cs
Normal file
119
lessons/Lesson04/Program.cs
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson04
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// ========== 方法调用 ==========
|
||||||
|
Console.WriteLine("=== 方法 ===");
|
||||||
|
SayHello("无言势");
|
||||||
|
int sum = Add(10, 20);
|
||||||
|
Console.WriteLine($"10 + 20 = {sum}");
|
||||||
|
|
||||||
|
// 带默认参数
|
||||||
|
Greet();
|
||||||
|
Greet("VRC");
|
||||||
|
|
||||||
|
// ========== 类和对象 ==========
|
||||||
|
Console.WriteLine("\n=== 类和对象 ===");
|
||||||
|
Person p1 = new Person("无言势", 25);
|
||||||
|
Person p2 = new Person("玩家A", 30);
|
||||||
|
|
||||||
|
p1.SayHi();
|
||||||
|
p2.SayHi();
|
||||||
|
|
||||||
|
// ========== 静态方法 ==========
|
||||||
|
Console.WriteLine("\n=== 静态方法 ===");
|
||||||
|
int result = MathHelper.Add(100, 200);
|
||||||
|
Console.WriteLine($"100 + 200 = {result}");
|
||||||
|
|
||||||
|
double pi = MathHelper.GetPI();
|
||||||
|
Console.WriteLine($"PI ≈ {pi}");
|
||||||
|
|
||||||
|
// ========== 面向对象练习 ==========
|
||||||
|
Console.WriteLine("\n=== 麦克风类 ===");
|
||||||
|
Microphone mic = new Microphone("USB麦克风", true);
|
||||||
|
mic.ToggleListening();
|
||||||
|
mic.ToggleListening();
|
||||||
|
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 方法定义 ==========
|
||||||
|
static void SayHello(string name)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"你好, {name}!");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Add(int a, int b)
|
||||||
|
{
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Greet(string name = "World")
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Hello, {name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 类定义 ==========
|
||||||
|
class Person
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
public int age;
|
||||||
|
|
||||||
|
// 构造函数
|
||||||
|
public Person(string name, int age)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SayHi()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"我是{name},今年{age}岁");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 静态类
|
||||||
|
static class MathHelper
|
||||||
|
{
|
||||||
|
public static int Add(int a, int b)
|
||||||
|
{
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double GetPI()
|
||||||
|
{
|
||||||
|
return 3.14159;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 麦克风类 - 结合项目练习
|
||||||
|
class Microphone
|
||||||
|
{
|
||||||
|
private string name;
|
||||||
|
private bool isListening;
|
||||||
|
|
||||||
|
public Microphone(string name, bool isListening)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.isListening = isListening;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleListening()
|
||||||
|
{
|
||||||
|
isListening = !isListening;
|
||||||
|
if (isListening)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[{name}] 开始监听...");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[{name}] 停止监听");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
lessons/Lesson05/Helpers/MathHelper.cs
Normal file
27
lessons/Lesson05/Helpers/MathHelper.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson05.Helpers
|
||||||
|
{
|
||||||
|
static class MathHelper
|
||||||
|
{
|
||||||
|
public static int Add(int a, int b)
|
||||||
|
{
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Multiply(int a, int b)
|
||||||
|
{
|
||||||
|
return a * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double Divide(int a, int b)
|
||||||
|
{
|
||||||
|
if (b == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("除数不能为0!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (double)a / b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lessons/Lesson05/Lesson05.csproj
Normal file
10
lessons/Lesson05/Lesson05.csproj
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
46
lessons/Lesson05/Models/Person.cs
Normal file
46
lessons/Lesson05/Models/Person.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson05.Models
|
||||||
|
{
|
||||||
|
class Person
|
||||||
|
{
|
||||||
|
// public: 任何地方都能访问
|
||||||
|
public string name;
|
||||||
|
|
||||||
|
// private: 只有本类内部能访问
|
||||||
|
private int age;
|
||||||
|
private string secret = "秘密信息";
|
||||||
|
|
||||||
|
// Property: 受保护的访问方式
|
||||||
|
public int Age
|
||||||
|
{
|
||||||
|
get { return age; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// value 是关键字,表示赋值时的右值
|
||||||
|
if (value < 0) value = 0;
|
||||||
|
if (value > 150) value = 150;
|
||||||
|
age = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造函数
|
||||||
|
public Person(string name, int age)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.Age = age; // 通过 Property 设置,自动限制范围
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SayHi()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"我是 {name},今年 {age} 岁");
|
||||||
|
Console.WriteLine($"我的秘密: {GetSecret()}"); // 本类内可以调用私有方法
|
||||||
|
}
|
||||||
|
|
||||||
|
// 私有方法:本类内部使用
|
||||||
|
private string GetSecret()
|
||||||
|
{
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
lessons/Lesson05/Program.cs
Normal file
42
lessons/Lesson05/Program.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
using System;
|
||||||
|
using Lesson05.Models;
|
||||||
|
using Lesson05.Services;
|
||||||
|
using Lesson05.Helpers;
|
||||||
|
|
||||||
|
namespace Lesson05
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("=== 多文件项目演示 ===\n");
|
||||||
|
|
||||||
|
// 使用 Models 里的类
|
||||||
|
Person p = new Person("无言势", 25);
|
||||||
|
p.SayHi();
|
||||||
|
|
||||||
|
// 使用 Property
|
||||||
|
p.Age = -5; // 会自动限制范围
|
||||||
|
Console.WriteLine($"设置后年龄: {p.Age}");
|
||||||
|
|
||||||
|
p.Age = 200;
|
||||||
|
Console.WriteLine($"设置后年龄: {p.Age}");
|
||||||
|
|
||||||
|
// 使用 Services
|
||||||
|
AudioService service = new AudioService();
|
||||||
|
service.StartListening();
|
||||||
|
service.StopListening();
|
||||||
|
|
||||||
|
// 使用 Helpers
|
||||||
|
int sum = MathHelper.Add(100, 200);
|
||||||
|
Console.WriteLine($"\n100 + 200 = {sum}");
|
||||||
|
|
||||||
|
// 演示 private 无法访问
|
||||||
|
// p.secret = "xxx"; // 编译错误
|
||||||
|
// p.SetSecret("xxx"); // 编译错误
|
||||||
|
|
||||||
|
Console.WriteLine("\n=== 演示完成 ===");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
lessons/Lesson05/Services/AudioService.cs
Normal file
39
lessons/Lesson05/Services/AudioService.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson05.Services
|
||||||
|
{
|
||||||
|
class AudioService
|
||||||
|
{
|
||||||
|
private bool isListening;
|
||||||
|
private string deviceName;
|
||||||
|
|
||||||
|
public AudioService()
|
||||||
|
{
|
||||||
|
this.deviceName = "默认麦克风";
|
||||||
|
this.isListening = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartListening()
|
||||||
|
{
|
||||||
|
if (!isListening)
|
||||||
|
{
|
||||||
|
isListening = true;
|
||||||
|
Console.WriteLine($"[{deviceName}] 开始监听...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopListening()
|
||||||
|
{
|
||||||
|
if (isListening)
|
||||||
|
{
|
||||||
|
isListening = false;
|
||||||
|
Console.WriteLine($"[{deviceName}] 停止监听");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsListening()
|
||||||
|
{
|
||||||
|
return isListening;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
lessons/Lesson06/Animals/Animal.cs
Normal file
25
lessons/Lesson06/Animals/Animal.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson06.Animals
|
||||||
|
{
|
||||||
|
class Animal
|
||||||
|
{
|
||||||
|
protected string name;
|
||||||
|
|
||||||
|
public Animal(string name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Eat()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{name} 在吃东西");
|
||||||
|
}
|
||||||
|
|
||||||
|
// virtual 允许子类重写
|
||||||
|
public virtual void Speak()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{name} 发出了声音");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
lessons/Lesson06/Animals/Cat.cs
Normal file
16
lessons/Lesson06/Animals/Cat.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson06.Animals
|
||||||
|
{
|
||||||
|
class Cat : Animal
|
||||||
|
{
|
||||||
|
public Cat(string name) : base(name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Speak()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{name} 喵喵喵~");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
lessons/Lesson06/Animals/Dog.cs
Normal file
27
lessons/Lesson06/Animals/Dog.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson06.Animals
|
||||||
|
{
|
||||||
|
class Dog : Animal
|
||||||
|
{
|
||||||
|
private string breed;
|
||||||
|
|
||||||
|
// base(name) 调用父类的构造函数
|
||||||
|
public Dog(string name, string breed) : base(name)
|
||||||
|
{
|
||||||
|
this.breed = breed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Info()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"名字: {name}, 品种: {breed}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重写父类方法
|
||||||
|
public override void Speak()
|
||||||
|
{
|
||||||
|
base.Speak(); // 先调用父类方法
|
||||||
|
Console.WriteLine($"{name} 汪汪汪!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
lessons/Lesson06/Devices/Camera.cs
Normal file
34
lessons/Lesson06/Devices/Camera.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson06.Devices
|
||||||
|
{
|
||||||
|
class Camera : IDevice
|
||||||
|
{
|
||||||
|
private string name;
|
||||||
|
public bool IsConnected { get; private set; }
|
||||||
|
|
||||||
|
public Camera(string name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.IsConnected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Connect()
|
||||||
|
{
|
||||||
|
if (!IsConnected)
|
||||||
|
{
|
||||||
|
IsConnected = true;
|
||||||
|
Console.WriteLine($"[{name}] 摄像头已连接");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Disconnect()
|
||||||
|
{
|
||||||
|
if (IsConnected)
|
||||||
|
{
|
||||||
|
IsConnected = false;
|
||||||
|
Console.WriteLine($"[{name}] 摄像头已断开");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lessons/Lesson06/Devices/IDevice.cs
Normal file
10
lessons/Lesson06/Devices/IDevice.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Lesson06.Devices
|
||||||
|
{
|
||||||
|
// 接口:定义契约
|
||||||
|
interface IDevice
|
||||||
|
{
|
||||||
|
void Connect();
|
||||||
|
void Disconnect();
|
||||||
|
bool IsConnected { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
34
lessons/Lesson06/Devices/Microphone.cs
Normal file
34
lessons/Lesson06/Devices/Microphone.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson06.Devices
|
||||||
|
{
|
||||||
|
class Microphone : IDevice
|
||||||
|
{
|
||||||
|
private string name;
|
||||||
|
public bool IsConnected { get; private set; }
|
||||||
|
|
||||||
|
public Microphone(string name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.IsConnected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Connect()
|
||||||
|
{
|
||||||
|
if (!IsConnected)
|
||||||
|
{
|
||||||
|
IsConnected = true;
|
||||||
|
Console.WriteLine($"[{name}] 麦克风已连接");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Disconnect()
|
||||||
|
{
|
||||||
|
if (IsConnected)
|
||||||
|
{
|
||||||
|
IsConnected = false;
|
||||||
|
Console.WriteLine($"[{name}] 麦克风已断开");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lessons/Lesson06/Lesson06.csproj
Normal file
10
lessons/Lesson06/Lesson06.csproj
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
55
lessons/Lesson06/Program.cs
Normal file
55
lessons/Lesson06/Program.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
using System;
|
||||||
|
using Lesson06.Animals;
|
||||||
|
using Lesson06.Devices;
|
||||||
|
|
||||||
|
namespace Lesson06
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("=== 继承演示 ===\n");
|
||||||
|
|
||||||
|
// 继承:Dog 继承了 Animal
|
||||||
|
Dog dog = new Dog("旺财", "金毛");
|
||||||
|
dog.Eat();
|
||||||
|
dog.Speak();
|
||||||
|
dog.Info();
|
||||||
|
|
||||||
|
Console.WriteLine("\n=== 方法重写 ===\n");
|
||||||
|
|
||||||
|
// 多态:Cat 和 Dog 重写了 Speak
|
||||||
|
Animal cat = new Cat("小猫");
|
||||||
|
Animal dog2 = new Dog("二狗", "哈士奇");
|
||||||
|
|
||||||
|
cat.Speak();
|
||||||
|
dog2.Speak();
|
||||||
|
|
||||||
|
Console.WriteLine("\n=== 接口演示 ===\n");
|
||||||
|
|
||||||
|
// 使用接口
|
||||||
|
Microphone mic = new Microphone("USB麦克风");
|
||||||
|
Camera cam = new Camera("RTSP摄像头");
|
||||||
|
|
||||||
|
mic.Connect();
|
||||||
|
mic.Disconnect();
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
|
||||||
|
cam.Connect();
|
||||||
|
cam.Disconnect();
|
||||||
|
|
||||||
|
Console.WriteLine("\n=== 接口多态 ===\n");
|
||||||
|
|
||||||
|
// 接口类型可以指向任何实现它的类
|
||||||
|
IDevice device1 = new Microphone("设备A");
|
||||||
|
IDevice device2 = new Camera("设备B");
|
||||||
|
|
||||||
|
device1.Connect();
|
||||||
|
device2.Connect();
|
||||||
|
|
||||||
|
Console.WriteLine("\n=== 完成 ===");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lessons/Lesson07/Lesson07.csproj
Normal file
10
lessons/Lesson07/Lesson07.csproj
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
107
lessons/Lesson07/Program.cs
Normal file
107
lessons/Lesson07/Program.cs
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Lesson07
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// ========== List<T> ==========
|
||||||
|
Console.WriteLine("=== List<T> 动态数组 ===\n");
|
||||||
|
|
||||||
|
List<string> transcriptHistory = new List<string>();
|
||||||
|
|
||||||
|
// 添加识别结果
|
||||||
|
transcriptHistory.Add("今天天气真不错");
|
||||||
|
transcriptHistory.Add("大家一起加油");
|
||||||
|
transcriptHistory.Add("这个功能很简单");
|
||||||
|
|
||||||
|
Console.WriteLine($"共有 {transcriptHistory.Count} 条记录:");
|
||||||
|
foreach (string text in transcriptHistory)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" - {text}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插入
|
||||||
|
transcriptHistory.Insert(1, "新插入的文字");
|
||||||
|
Console.WriteLine($"\n插入后共有 {transcriptHistory.Count} 条记录:");
|
||||||
|
foreach (string text in transcriptHistory)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" - {text}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
transcriptHistory.Remove("大家一起加油");
|
||||||
|
Console.WriteLine($"\n删除后共有 {transcriptHistory.Count} 条记录");
|
||||||
|
|
||||||
|
// 初始化器
|
||||||
|
List<string> fruits = new List<string>() { "苹果", "香蕉", "橙子" };
|
||||||
|
Console.WriteLine($"\n水果列表:{string.Join(", ", fruits)}");
|
||||||
|
|
||||||
|
// ========== Dictionary<K, V> ==========
|
||||||
|
Console.WriteLine("\n=== Dictionary<K, V> 键值对 ===\n");
|
||||||
|
|
||||||
|
// 设备配置
|
||||||
|
Dictionary<string, string> deviceConfig = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
["name"] = "USB麦克风",
|
||||||
|
["sampleRate"] = "16000",
|
||||||
|
["channels"] = "1"
|
||||||
|
};
|
||||||
|
|
||||||
|
Console.WriteLine("设备配置:");
|
||||||
|
foreach (KeyValuePair<string, string> kv in deviceConfig)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" {kv.Key}: {kv.Value}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 访问单个值
|
||||||
|
Console.WriteLine($"\n设备名称: {deviceConfig["name"]}");
|
||||||
|
|
||||||
|
// 安全访问
|
||||||
|
if (deviceConfig.TryGetValue("notExist", out string value))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"找到: {value}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("键不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置选项
|
||||||
|
Dictionary<string, bool> settings = new Dictionary<string, bool>()
|
||||||
|
{
|
||||||
|
["autoConnect"] = true,
|
||||||
|
["vad"] = true,
|
||||||
|
["debug"] = false
|
||||||
|
};
|
||||||
|
|
||||||
|
Console.WriteLine("\n设置选项:");
|
||||||
|
foreach (string key in settings.Keys)
|
||||||
|
{
|
||||||
|
string status = settings[key] ? "开启" : "关闭";
|
||||||
|
Console.WriteLine($" {key}: {status}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 数字集合 ==========
|
||||||
|
Console.WriteLine("\n=== 数字 List 操作 ===\n");
|
||||||
|
|
||||||
|
List<int> scores = new List<int>() { 85, 92, 78, 95, 88 };
|
||||||
|
|
||||||
|
Console.WriteLine($"原始成绩:{string.Join(", ", scores)}");
|
||||||
|
|
||||||
|
scores.Sort();
|
||||||
|
Console.WriteLine($"排序后:{string.Join(", ", scores)}");
|
||||||
|
|
||||||
|
scores.Reverse();
|
||||||
|
Console.WriteLine($"反转后:{string.Join(", ", scores)}");
|
||||||
|
|
||||||
|
Console.WriteLine($"最高分:{scores[0]}");
|
||||||
|
Console.WriteLine($"包含 100? {scores.Contains(100)}");
|
||||||
|
Console.WriteLine($"包含 95? {scores.Contains(95)}");
|
||||||
|
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lessons/Lesson08/Lesson08.csproj
Normal file
10
lessons/Lesson08/Lesson08.csproj
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
187
lessons/Lesson08/Program.cs
Normal file
187
lessons/Lesson08/Program.cs
Normal file
|
|
@ -0,0 +1,187 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson08
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("=== 异常处理演示 ===\n");
|
||||||
|
|
||||||
|
// ========== 基本 try-catch ==========
|
||||||
|
Console.WriteLine("--- 基本 try-catch ---");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int[] numbers = { 1, 2, 3 };
|
||||||
|
Console.WriteLine(numbers[10]);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"捕获异常: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 捕获特定异常 ==========
|
||||||
|
Console.WriteLine("\n--- 捕获特定异常 ---");
|
||||||
|
string[] inputs = { "123", "abc", "9999999999999" };
|
||||||
|
|
||||||
|
foreach (string input in inputs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int num = int.Parse(input);
|
||||||
|
Console.WriteLine($"转换成功: {num}");
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\"{input}\" 格式错误,不是数字");
|
||||||
|
}
|
||||||
|
catch (OverflowException)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\"{input}\" 数字太大");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== throw 抛出异常 ==========
|
||||||
|
Console.WriteLine("\n--- throw 抛出异常 ---");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetAge(-5);
|
||||||
|
}
|
||||||
|
catch (ArgumentException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"捕获到: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetAge(200);
|
||||||
|
}
|
||||||
|
catch (ArgumentException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"捕获到: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
SetAge(25); // 正常
|
||||||
|
SetAge(0); // 正常
|
||||||
|
|
||||||
|
// ========== 实际项目场景 ==========
|
||||||
|
Console.WriteLine("\n--- 设备连接场景 ---");
|
||||||
|
MicrophoneDevice mic = new MicrophoneDevice("USB麦克风");
|
||||||
|
|
||||||
|
// 场景1:设备未连接
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mic.StartListening();
|
||||||
|
}
|
||||||
|
catch (DeviceNotConnectedException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"错误: {ex.Message}");
|
||||||
|
Console.WriteLine("建议:请检查设备连接");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 场景2:连接后正常操作
|
||||||
|
mic.Connect();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mic.StartListening();
|
||||||
|
Console.WriteLine("麦克风开始监听...");
|
||||||
|
mic.StopListening();
|
||||||
|
Console.WriteLine("麦克风停止监听...");
|
||||||
|
}
|
||||||
|
catch (DeviceNotConnectedException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"错误: {ex.Message}");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
mic.Disconnect();
|
||||||
|
Console.WriteLine("设备已断开");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== finally 演示 ==========
|
||||||
|
Console.WriteLine("\n--- finally 执行时机 ---");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine("try 块执行");
|
||||||
|
// int x = 1 / 0; // 解开这行会跳到 catch
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Console.WriteLine("catch 块执行");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Console.WriteLine("finally 块总是执行");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\n=== 演示完成 ===");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== throw 示例 ==========
|
||||||
|
static void SetAge(int age)
|
||||||
|
{
|
||||||
|
if (age < 0 || age > 150)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"年龄必须在 0-150 之间,当前: {age}");
|
||||||
|
}
|
||||||
|
Console.WriteLine($"年龄设置为: {age}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 自定义异常 ==========
|
||||||
|
class DeviceNotConnectedException : Exception
|
||||||
|
{
|
||||||
|
public DeviceNotConnectedException(string message) : base(message) { }
|
||||||
|
public DeviceNotConnectedException(string message, Exception inner) : base(message, inner) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 设备类 ==========
|
||||||
|
class MicrophoneDevice
|
||||||
|
{
|
||||||
|
private string name;
|
||||||
|
private bool isConnected;
|
||||||
|
private bool isListening;
|
||||||
|
|
||||||
|
public MicrophoneDevice(string name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.isConnected = false;
|
||||||
|
this.isListening = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Connect()
|
||||||
|
{
|
||||||
|
isConnected = true;
|
||||||
|
Console.WriteLine($"[{name}] 设备已连接");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Disconnect()
|
||||||
|
{
|
||||||
|
isConnected = false;
|
||||||
|
Console.WriteLine($"[{name}] 设备已断开");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartListening()
|
||||||
|
{
|
||||||
|
if (!isConnected)
|
||||||
|
{
|
||||||
|
throw new DeviceNotConnectedException($"{name} 未连接,无法开始监听");
|
||||||
|
}
|
||||||
|
if (isListening)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"{name} 已经在监听中");
|
||||||
|
}
|
||||||
|
isListening = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopListening()
|
||||||
|
{
|
||||||
|
if (!isListening)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"{name} 没有在监听");
|
||||||
|
}
|
||||||
|
isListening = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lessons/Lesson09/Lesson09.csproj
Normal file
10
lessons/Lesson09/Lesson09.csproj
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
103
lessons/Lesson09/Program.cs
Normal file
103
lessons/Lesson09/Program.cs
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Lesson09
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
string basePath = Directory.GetCurrentDirectory();
|
||||||
|
string testFile = Path.Combine(basePath, "test.txt");
|
||||||
|
string configFile = Path.Combine(basePath, "config.json");
|
||||||
|
string logFile = Path.Combine(basePath, "app.log");
|
||||||
|
|
||||||
|
Console.WriteLine("=== 文件读写演示 ===\n");
|
||||||
|
|
||||||
|
// ========== 写入文本文件 ==========
|
||||||
|
Console.WriteLine("--- 写入文本文件 ---");
|
||||||
|
string content = "第一行:无言势字幕\n第二行:VRChat 语音识别工具";
|
||||||
|
File.WriteAllText(testFile, content);
|
||||||
|
Console.WriteLine($"已写入: {testFile}");
|
||||||
|
|
||||||
|
// ========== 读取文本文件 ==========
|
||||||
|
Console.WriteLine("\n--- 读取文本文件 ---");
|
||||||
|
string readContent = File.ReadAllText(testFile);
|
||||||
|
Console.WriteLine("文件内容:");
|
||||||
|
Console.WriteLine(readContent);
|
||||||
|
|
||||||
|
// ========== 按行读写 ==========
|
||||||
|
Console.WriteLine("\n--- 按行读取 ---");
|
||||||
|
string[] lines = File.ReadAllLines(testFile);
|
||||||
|
for (int i = 0; i < lines.Length; i++)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"行 {i + 1}: {lines[i]}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== JSON 配置 ==========
|
||||||
|
Console.WriteLine("\n--- JSON 配置读写 ---");
|
||||||
|
|
||||||
|
// 创建设置对象
|
||||||
|
AppSettings settings = new AppSettings
|
||||||
|
{
|
||||||
|
Sensitivity = 75,
|
||||||
|
AutoConnect = true,
|
||||||
|
VadEnabled = true,
|
||||||
|
Language = "zh-CN"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 序列化为 JSON
|
||||||
|
string json = JsonSerializer.Serialize(settings, new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
WriteIndented = true // 格式化输出
|
||||||
|
});
|
||||||
|
File.WriteAllText(configFile, json);
|
||||||
|
Console.WriteLine("已保存配置: config.json");
|
||||||
|
Console.WriteLine(json);
|
||||||
|
|
||||||
|
// 反序列化
|
||||||
|
string loadedJson = File.ReadAllText(configFile);
|
||||||
|
AppSettings loadedSettings = JsonSerializer.Deserialize<AppSettings>(loadedJson);
|
||||||
|
Console.WriteLine("\n读取的配置:");
|
||||||
|
Console.WriteLine($" 灵敏度: {loadedSettings.Sensitivity}");
|
||||||
|
Console.WriteLine($" 自动连接: {loadedSettings.AutoConnect}");
|
||||||
|
Console.WriteLine($" VAD: {loadedSettings.VadEnabled}");
|
||||||
|
Console.WriteLine($" 语言: {loadedSettings.Language}");
|
||||||
|
|
||||||
|
// ========== 追加日志 ==========
|
||||||
|
Console.WriteLine("\n--- 追加日志 ---");
|
||||||
|
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
string logEntry = $"[{timestamp}] 应用启动\n";
|
||||||
|
File.AppendAllText(logFile, logEntry);
|
||||||
|
Console.WriteLine($"已追加日志: {logFile}");
|
||||||
|
|
||||||
|
// ========== 文件操作 ==========
|
||||||
|
Console.WriteLine("\n--- 文件操作 ---");
|
||||||
|
Console.WriteLine($"文件是否存在: {File.Exists(testFile)}");
|
||||||
|
Console.WriteLine($"文件大小: {new FileInfo(testFile).Length} 字节");
|
||||||
|
Console.WriteLine($"完整路径: {Path.GetFullPath(testFile)}");
|
||||||
|
Console.WriteLine($"扩展名: {Path.GetExtension(testFile)}");
|
||||||
|
|
||||||
|
// ========== 清理 ==========
|
||||||
|
Console.WriteLine("\n--- 清理测试文件 ---");
|
||||||
|
if (File.Exists(testFile)) File.Delete(testFile);
|
||||||
|
if (File.Exists(configFile)) File.Delete(configFile);
|
||||||
|
if (File.Exists(logFile)) File.Delete(logFile);
|
||||||
|
Console.WriteLine("已删除测试文件");
|
||||||
|
|
||||||
|
Console.WriteLine("\n=== 演示完成 ===");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 配置类 ==========
|
||||||
|
class AppSettings
|
||||||
|
{
|
||||||
|
public int Sensitivity { get; set; } = 70;
|
||||||
|
public bool AutoConnect { get; set; } = true;
|
||||||
|
public bool VadEnabled { get; set; } = true;
|
||||||
|
public string Language { get; set; } = "zh-CN";
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lessons/Lesson10/Lesson10.csproj
Normal file
10
lessons/Lesson10/Lesson10.csproj
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
136
lessons/Lesson10/Program.cs
Normal file
136
lessons/Lesson10/Program.cs
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson10
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("=== 委托和事件演示 ===\n");
|
||||||
|
|
||||||
|
// ========== 委托 ==========
|
||||||
|
Console.WriteLine("--- 委托 ---");
|
||||||
|
|
||||||
|
// Action: 无返回值的委托
|
||||||
|
Action<string> print = (msg) => Console.WriteLine($"打印: {msg}");
|
||||||
|
print("Hello World");
|
||||||
|
|
||||||
|
// Func: 有返回值的委托
|
||||||
|
Func<int, int, int> add = (a, b) => a + b;
|
||||||
|
Func<int, int, int> multiply = (a, b) => a * b;
|
||||||
|
|
||||||
|
Console.WriteLine($"add(3, 5) = {add(3, 5)}");
|
||||||
|
Console.WriteLine($"multiply(3, 5) = {multiply(3, 5)}");
|
||||||
|
|
||||||
|
// ========== 事件 ==========
|
||||||
|
Console.WriteLine("\n--- 事件 ---");
|
||||||
|
|
||||||
|
Microphone mic = new Microphone("USB麦克风");
|
||||||
|
|
||||||
|
// 订阅事件 - 收到文字时
|
||||||
|
mic.OnTranscriptReady += (text) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[UI更新] 显示文字: {text}");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 订阅事件 - 开始监听
|
||||||
|
mic.OnListeningStarted += () =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("[UI更新] 开始播放动画");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 订阅事件 - 停止监听
|
||||||
|
mic.OnListeningStopped += () =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("[UI更新] 停止动画");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 订阅事件 - 错误处理
|
||||||
|
mic.OnError += (error) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[UI更新] 显示错误: {error}");
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== 模拟使用流程 ==========
|
||||||
|
Console.WriteLine("\n--- 模拟识别流程 ---");
|
||||||
|
|
||||||
|
// 正常流程
|
||||||
|
mic.StartListening();
|
||||||
|
mic.TranscriptDetected("今天天气真不错");
|
||||||
|
mic.TranscriptDetected("大家一起加油");
|
||||||
|
mic.StopListening();
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
|
||||||
|
// 模拟错误
|
||||||
|
mic.StartListening();
|
||||||
|
mic.SimulateError("设备断开连接");
|
||||||
|
mic.StopListening();
|
||||||
|
|
||||||
|
Console.WriteLine("\n=== 演示完成 ===");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 麦克风类(带事件) ==========
|
||||||
|
class Microphone
|
||||||
|
{
|
||||||
|
private string name;
|
||||||
|
private bool isListening;
|
||||||
|
|
||||||
|
// 事件声明
|
||||||
|
public event Action<string> OnTranscriptReady; // 识别出文字
|
||||||
|
public event Action OnListeningStarted; // 开始监听
|
||||||
|
public event Action OnListeningStopped; // 停止监听
|
||||||
|
public event Action<string> OnError; // 错误
|
||||||
|
|
||||||
|
public Microphone(string name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.isListening = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartListening()
|
||||||
|
{
|
||||||
|
if (isListening)
|
||||||
|
{
|
||||||
|
OnError?.Invoke("已经在监听中");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isListening = true;
|
||||||
|
Console.WriteLine($"[{name}] 开始监听");
|
||||||
|
OnListeningStarted?.Invoke(); // 通知所有订阅者
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopListening()
|
||||||
|
{
|
||||||
|
if (!isListening)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isListening = false;
|
||||||
|
Console.WriteLine($"[{name}] 停止监听");
|
||||||
|
OnListeningStopped?.Invoke(); // 通知所有订阅者
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TranscriptDetected(string text)
|
||||||
|
{
|
||||||
|
if (!isListening)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"[{name}] 识别: {text}");
|
||||||
|
OnTranscriptReady?.Invoke(text); // 通知所有订阅者
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟错误
|
||||||
|
public void SimulateError(string error)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[{name}] 错误: {error}");
|
||||||
|
OnError?.Invoke(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
lessons/Lesson_One/Lesson01_HelloWorld.cs
Normal file
24
lessons/Lesson_One/Lesson01_HelloWorld.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Lesson 01: Hello World
|
||||||
|
// 目标:熟悉 C# 基本结构和输出
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace CSharpLearning
|
||||||
|
{
|
||||||
|
class Lesson01_HelloWorld
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// 打印 hello world
|
||||||
|
Console.WriteLine("Hello, World!");
|
||||||
|
Console.WriteLine("你好,C#!");
|
||||||
|
|
||||||
|
// 打印带格式
|
||||||
|
string name = "无言势字幕";
|
||||||
|
Console.WriteLine($"项目名称: {name}");
|
||||||
|
|
||||||
|
// 等待输入(防止窗口关闭)
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lessons/Lesson_One/Lesson_One.csproj
Normal file
10
lessons/Lesson_One/Lesson_One.csproj
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
67
lessons/Lesson_One/Program.cs
Normal file
67
lessons/Lesson_One/Program.cs
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Lesson_One
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// ========== 变量 ==========
|
||||||
|
int age = 25;
|
||||||
|
double height = 175.5;
|
||||||
|
string name = "无言势字幕";
|
||||||
|
char grade = 'A';
|
||||||
|
bool isActive = true;
|
||||||
|
|
||||||
|
Console.WriteLine("=== 变量 ===");
|
||||||
|
Console.WriteLine($"姓名: {name}");
|
||||||
|
Console.WriteLine($"年龄: {age}");
|
||||||
|
Console.WriteLine($"身高: {height}cm");
|
||||||
|
Console.WriteLine($"等级: {grade}");
|
||||||
|
Console.WriteLine($"状态: {isActive}");
|
||||||
|
|
||||||
|
// ========== var 自动推断 ==========
|
||||||
|
Console.WriteLine("\n=== var 自动推断 ===");
|
||||||
|
var message = "这是 string 类型";
|
||||||
|
var number = 42; // 推断为 int
|
||||||
|
Console.WriteLine($"message 是: {message.GetType()}");
|
||||||
|
Console.WriteLine($"number 是: {number.GetType()}");
|
||||||
|
|
||||||
|
// ========== 常量 ==========
|
||||||
|
Console.WriteLine("\n=== 常量 ===");
|
||||||
|
const int MAX_RETRY = 3;
|
||||||
|
const string VERSION = "v1.0";
|
||||||
|
Console.WriteLine($"最大重试次数: {MAX_RETRY}");
|
||||||
|
Console.WriteLine($"版本: {VERSION}");
|
||||||
|
|
||||||
|
// ========== 类型转换 ==========
|
||||||
|
Console.WriteLine("\n=== 类型转换 ===");
|
||||||
|
int i = 10;
|
||||||
|
double d = i; // 隐式转换
|
||||||
|
Console.WriteLine($"int -> double: {d}");
|
||||||
|
|
||||||
|
double d2 = 3.14;
|
||||||
|
int i2 = (int)d2; // 显式转换
|
||||||
|
Console.WriteLine($"double -> int: {i2}");
|
||||||
|
|
||||||
|
string s = i.ToString();
|
||||||
|
Console.WriteLine($"int -> string: {s}");
|
||||||
|
|
||||||
|
int i3 = int.Parse("123");
|
||||||
|
Console.WriteLine($"string \"123\" -> int: {i3}");
|
||||||
|
|
||||||
|
// ========== 输入练习 ==========
|
||||||
|
Console.WriteLine("\n=== 输入练习 ===");
|
||||||
|
Console.Write("请输入你的名字: ");
|
||||||
|
string inputName = Console.ReadLine();
|
||||||
|
Console.Write($"你好, {inputName}! ");
|
||||||
|
|
||||||
|
Console.Write("请输入年龄: ");
|
||||||
|
string ageInput = Console.ReadLine();
|
||||||
|
int userAge = int.Parse(ageInput);
|
||||||
|
Console.WriteLine($"你 {userAge} 岁了");
|
||||||
|
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
notes/01_CSharp_Basics.md
Normal file
46
notes/01_CSharp_Basics.md
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
# C# 基础入门
|
||||||
|
|
||||||
|
## 环境确认
|
||||||
|
|
||||||
|
- .NET SDK: `dotnet --version`
|
||||||
|
- 编辑器: VS Code + C# Dev Kit (可选) 或 Rider
|
||||||
|
|
||||||
|
## 常用命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 创建新项目
|
||||||
|
dotnet new console -n MyProject
|
||||||
|
|
||||||
|
# 运行
|
||||||
|
dotnet run
|
||||||
|
|
||||||
|
# 构建发布
|
||||||
|
dotnet publish -c Release
|
||||||
|
```
|
||||||
|
|
||||||
|
## 基本结构
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MyProject
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Hello, World!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 关键概念
|
||||||
|
|
||||||
|
| 概念 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `using` | 引入命名空间,类似 Python import |
|
||||||
|
| `namespace` | 命名空间,防止命名冲突 |
|
||||||
|
| `class` | 类,一切皆对象 |
|
||||||
|
| `static void Main` | 程序入口点 |
|
||||||
|
| `Console.WriteLine` | 输出到终端 |
|
||||||
62
notes/02_Variables_and_Types.md
Normal file
62
notes/02_Variables_and_Types.md
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
# 第二课:变量和数据类型
|
||||||
|
|
||||||
|
## 基本数据类型
|
||||||
|
|
||||||
|
| 类型 | 说明 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| `int` | 整数 | `int age = 25;` |
|
||||||
|
| `double` | 小数 | `double pi = 3.14;` |
|
||||||
|
| `string` | 字符串 | `string name = "无言势";` |
|
||||||
|
| `char` | 单字符 | `char grade = 'A';` |
|
||||||
|
| `bool` | 布尔值 | `bool isActive = true;` |
|
||||||
|
| `var` | 自动推断 | `var msg = "自动推断为string";` |
|
||||||
|
|
||||||
|
## 声明和赋值
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 声明 + 赋值
|
||||||
|
int score = 100;
|
||||||
|
|
||||||
|
// 先声明,后赋值
|
||||||
|
int score;
|
||||||
|
score = 100;
|
||||||
|
|
||||||
|
// 多个变量
|
||||||
|
int a = 1, b = 2, c = 3;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常量
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
const double PI = 3.14159; // const 声明后不可修改
|
||||||
|
```
|
||||||
|
|
||||||
|
## 类型转换
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 隐式转换(自动)
|
||||||
|
int i = 10;
|
||||||
|
double d = i; // int -> double
|
||||||
|
|
||||||
|
// 显式转换(强制)
|
||||||
|
double d = 3.14;
|
||||||
|
int i = (int)d; // double -> int,结果是 3
|
||||||
|
|
||||||
|
// ToString / Parse
|
||||||
|
int i = int.Parse("123");
|
||||||
|
string s = i.ToString();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 输入输出
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 输出
|
||||||
|
Console.WriteLine("Hello"); // 换行
|
||||||
|
Console.Write("Hello"); // 不换行
|
||||||
|
|
||||||
|
// 输入(返回 string)
|
||||||
|
string name = Console.ReadLine();
|
||||||
|
|
||||||
|
// 输入数字要转换
|
||||||
|
int age = int.Parse(Console.ReadLine());
|
||||||
|
```
|
||||||
102
notes/03_Conditions_and_Loops.md
Normal file
102
notes/03_Conditions_and_Loops.md
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
# 第三课:条件判断和循环
|
||||||
|
|
||||||
|
## if / else 判断
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
int score = 85;
|
||||||
|
|
||||||
|
if (score >= 90)
|
||||||
|
{
|
||||||
|
Console.WriteLine("优秀");
|
||||||
|
}
|
||||||
|
else if (score >= 60)
|
||||||
|
{
|
||||||
|
Console.WriteLine("及格");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("不及格");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 三元运算符(简单判断)
|
||||||
|
string result = score >= 60 ? "及格" : "不及格";
|
||||||
|
```
|
||||||
|
|
||||||
|
## switch 选择
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
int day = 3;
|
||||||
|
|
||||||
|
switch (day)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
Console.WriteLine("星期一");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Console.WriteLine("星期二");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
Console.WriteLine("星期三");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine("其他");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## for 循环
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 传统 for
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
Console.WriteLine(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历数组
|
||||||
|
string[] names = { "A", "B", "C" };
|
||||||
|
for (int i = 0; i < names.Length; i++)
|
||||||
|
{
|
||||||
|
Console.WriteLine(names[i]);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## foreach 循环(更简洁)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
string[] names = { "A", "B", "C" };
|
||||||
|
|
||||||
|
foreach (string name in names)
|
||||||
|
{
|
||||||
|
Console.WriteLine(name);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## while 循环
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
int i = 0;
|
||||||
|
while (i < 5)
|
||||||
|
{
|
||||||
|
Console.WriteLine(i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先执行再判断
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Console.WriteLine(i);
|
||||||
|
i++;
|
||||||
|
} while (i < 5);
|
||||||
|
```
|
||||||
|
|
||||||
|
## break 和 continue
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
if (i == 3) continue; // 跳过 i=3
|
||||||
|
if (i == 7) break; // 退出循环
|
||||||
|
Console.WriteLine(i);
|
||||||
|
}
|
||||||
|
```
|
||||||
91
notes/04_Methods_and_Classes.md
Normal file
91
notes/04_Methods_and_Classes.md
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
# 第四课:方法(函数)和类
|
||||||
|
|
||||||
|
## 方法(函数)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 无返回值
|
||||||
|
void SayHello(string name)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"你好, {name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 有返回值
|
||||||
|
int Add(int a, int b)
|
||||||
|
{
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 带默认参数
|
||||||
|
void Greet(string name = "World")
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Hello, {name}");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 方法调用
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
SayHello("无言势"); // 调用无返回值方法
|
||||||
|
int sum = Add(1, 2); // 调用有返回值方法
|
||||||
|
Console.WriteLine(sum); // 输出 3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 类(Class)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
class Person
|
||||||
|
{
|
||||||
|
// 字段(属性)
|
||||||
|
public string name;
|
||||||
|
public int age;
|
||||||
|
|
||||||
|
// 构造函数
|
||||||
|
public Person(string name, int age)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方法
|
||||||
|
public void SayHi()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"我是{name},今年{age}岁");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 创建对象
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Person p = new Person("无言势", 25);
|
||||||
|
p.SayHi();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 访问修饰符
|
||||||
|
|
||||||
|
| 修饰符 | 访问范围 |
|
||||||
|
|--------|----------|
|
||||||
|
| `public` | 任何地方都能访问 |
|
||||||
|
| `private` | 只有本类内部能访问 |
|
||||||
|
| `internal` | 同程序集内访问 |
|
||||||
|
|
||||||
|
## 静态(static)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
class MathHelper
|
||||||
|
{
|
||||||
|
public static int Add(int a, int b)
|
||||||
|
{
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用不需要 new
|
||||||
|
int result = MathHelper.Add(1, 2);
|
||||||
|
```
|
||||||
114
notes/05_MultiFile_and_Access_Modifiers.md
Normal file
114
notes/05_MultiFile_and_Access_Modifiers.md
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
# 第五课:多文件项目和访问修饰符
|
||||||
|
|
||||||
|
## 多文件项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
Lesson05/
|
||||||
|
├── Program.cs // 入口,只管 Main
|
||||||
|
├── Models/
|
||||||
|
│ ├── Person.cs // 数据模型
|
||||||
|
│ └── Microphone.cs // 麦克风类
|
||||||
|
├── Helpers/
|
||||||
|
│ └── MathHelper.cs // 工具类
|
||||||
|
└── Services/
|
||||||
|
└── AudioService.cs // 服务类
|
||||||
|
```
|
||||||
|
|
||||||
|
**关键规则**:
|
||||||
|
- 同一项目内,所有 `.cs` 文件自动互相可见(不需要 import)
|
||||||
|
- 用文件夹组织,但编译时所有文件合并成一个程序集
|
||||||
|
|
||||||
|
## public vs private 核心区别
|
||||||
|
|
||||||
|
| 修饰符 | 类内访问 | 类外访问 | 继承访问 |
|
||||||
|
|--------|----------|----------|----------|
|
||||||
|
| `public` | ✓ | ✓ | ✓ |
|
||||||
|
| `private` | ✓ | ✗ | ✗ |
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
class Person
|
||||||
|
{
|
||||||
|
public string name; // 任何地方都能读写
|
||||||
|
private int age; // 只有 Person 内部能访问
|
||||||
|
private string secret; // 外部无法访问
|
||||||
|
|
||||||
|
public void SetAge(int age)
|
||||||
|
{
|
||||||
|
// 公有方法内部可以访问私有字段
|
||||||
|
if (age > 0 && age < 150)
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetAge()
|
||||||
|
{
|
||||||
|
return this.age; // 通过方法间接访问
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Program.cs
|
||||||
|
Person p = new Person("无言势");
|
||||||
|
p.name = "新名字"; // OK,public
|
||||||
|
p.age = 25; // 编译错误,private
|
||||||
|
p.SetAge(25); // OK,通过公有方法
|
||||||
|
```
|
||||||
|
|
||||||
|
## 为什么要 private?
|
||||||
|
|
||||||
|
**数据保护**:防止无效值
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private int age;
|
||||||
|
|
||||||
|
// 外部不能直接 age = -100
|
||||||
|
// 必须通过方法验证后设置
|
||||||
|
public void SetAge(int age)
|
||||||
|
{
|
||||||
|
if (age < 0) age = 0;
|
||||||
|
if (age > 150) age = 150;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**封装**:内部实现可以随时改,不影响外部
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 内部存储从 int 改成 DateTime 都可以
|
||||||
|
// 只要 public 方法签名不变,外部代码不用改
|
||||||
|
```
|
||||||
|
|
||||||
|
## 其他访问修饰符
|
||||||
|
|
||||||
|
| 修饰符 | 说明 |
|
||||||
|
|--------|------|
|
||||||
|
| `public` | 完全公开 |
|
||||||
|
| `private` | 仅本类 |
|
||||||
|
| `protected` | 本类 + 子类 |
|
||||||
|
| `internal` | 同项目内 |
|
||||||
|
|
||||||
|
## 属性(Property)- 介于 public/private 之间
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
class Person
|
||||||
|
{
|
||||||
|
private int _age;
|
||||||
|
|
||||||
|
public int Age
|
||||||
|
{
|
||||||
|
get { return _age; } // 读取
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0) value = 0; // 写入时验证
|
||||||
|
if (value > 150) value = 150;
|
||||||
|
_age = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
Person p = new Person();
|
||||||
|
p.Age = 25; // 自动调用 set
|
||||||
|
int a = p.Age; // 自动调用 get
|
||||||
|
```
|
||||||
191
notes/06_Inheritance_and_Interface.md
Normal file
191
notes/06_Inheritance_and_Interface.md
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
# 第六课:继承和接口
|
||||||
|
|
||||||
|
## 继承(Inheritance)
|
||||||
|
|
||||||
|
子类继承父类的属性和方法,避免重复代码。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 父类
|
||||||
|
class Animal
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
public void Eat()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{name} 在吃东西");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子类
|
||||||
|
class Dog : Animal
|
||||||
|
{
|
||||||
|
public void Bark()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{name} 在叫: 汪汪!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
Dog dog = new Dog();
|
||||||
|
dog.name = "旺财";
|
||||||
|
dog.Eat(); // 继承自 Animal
|
||||||
|
dog.Bark(); // 自己独有的
|
||||||
|
```
|
||||||
|
|
||||||
|
## 方法重写(override)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 父类 virtual 方法
|
||||||
|
class Animal
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
public virtual void Speak()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{name} 发出了声音");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子类重写
|
||||||
|
class Cat : Animal
|
||||||
|
{
|
||||||
|
public override void Speak()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{name} 喵喵喵~");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
Animal a = new Cat();
|
||||||
|
a.name = "小猫";
|
||||||
|
a.Speak(); // 输出: 小猫 喵喵喵~
|
||||||
|
```
|
||||||
|
|
||||||
|
## base 关键字
|
||||||
|
|
||||||
|
子类调用父类的方法/构造函数:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
class Dog : Animal
|
||||||
|
{
|
||||||
|
public string breed;
|
||||||
|
|
||||||
|
public Dog(string name, string breed) : base(name)
|
||||||
|
{
|
||||||
|
this.breed = breed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Speak()
|
||||||
|
{
|
||||||
|
base.Speak(); // 先调用父类方法
|
||||||
|
Console.WriteLine($"{name} 汪汪!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 访问修饰符 protected
|
||||||
|
|
||||||
|
| 修饰符 | 任何地方 | 继承访问 |
|
||||||
|
|--------|----------|----------|
|
||||||
|
| `private` | ✗ | ✗ |
|
||||||
|
| `protected` | ✗ | ✓ |
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
class Animal
|
||||||
|
{
|
||||||
|
protected string name; // private 的话子类也访问不到
|
||||||
|
}
|
||||||
|
|
||||||
|
class Dog : Animal
|
||||||
|
{
|
||||||
|
public void Test()
|
||||||
|
{
|
||||||
|
name = "旺财"; // protected 可以访问
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 接口(Interface)
|
||||||
|
|
||||||
|
接口 = 约定/契约,定义必须实现的方法。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 定义接口
|
||||||
|
interface IFlyable
|
||||||
|
{
|
||||||
|
void Fly(); // 不写实现
|
||||||
|
int MaxAltitude { get; } // 可以有属性
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实现接口
|
||||||
|
class Bird : IFlyable
|
||||||
|
{
|
||||||
|
public int MaxAltitude => 1000;
|
||||||
|
|
||||||
|
public void Fly()
|
||||||
|
{
|
||||||
|
Console.WriteLine("鸟儿在飞翔");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Plane : IFlyable
|
||||||
|
{
|
||||||
|
public int MaxAltitude => 10000;
|
||||||
|
|
||||||
|
public void Fly()
|
||||||
|
{
|
||||||
|
Console.WriteLine("飞机在飞翔");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 接口 vs 继承
|
||||||
|
|
||||||
|
| | 继承 | 接口 |
|
||||||
|
|---|---|---|
|
||||||
|
| 关键词 | `class A : B` | `class A : IB` |
|
||||||
|
| 只能继承一个父类 | ✓ | 可以实现多个接口 |
|
||||||
|
| 继承获得代码 | ✓ | 只获得"约定" |
|
||||||
|
| 何时用 | 代码复用 | 约定行为 |
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 一个类只能继承一个父类
|
||||||
|
class Dog : Animal { }
|
||||||
|
|
||||||
|
// 但可以实现多个接口
|
||||||
|
class Duck : Animal, IFlyable, ISwimable
|
||||||
|
{
|
||||||
|
public void Fly() { }
|
||||||
|
public void Swim() { }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 例子:设备驱动架构
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 设备接口
|
||||||
|
interface IDevice
|
||||||
|
{
|
||||||
|
void Connect();
|
||||||
|
void Disconnect();
|
||||||
|
bool IsConnected { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 麦克风设备
|
||||||
|
class Microphone : IDevice
|
||||||
|
{
|
||||||
|
public bool IsConnected { get; private set; }
|
||||||
|
|
||||||
|
public void Connect()
|
||||||
|
{
|
||||||
|
Console.WriteLine("麦克风连接");
|
||||||
|
IsConnected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Disconnect()
|
||||||
|
{
|
||||||
|
Console.WriteLine("麦克风断开");
|
||||||
|
IsConnected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
135
notes/07_Collections.md
Normal file
135
notes/07_Collections.md
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
# 第七课:集合(List / Dictionary)
|
||||||
|
|
||||||
|
## List<T> 动态数组
|
||||||
|
|
||||||
|
`T` 是泛型,占位符,使用时替换成具体类型。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
// 声明
|
||||||
|
List<string> names = new List<string>();
|
||||||
|
|
||||||
|
// 添加
|
||||||
|
names.Add("无言势");
|
||||||
|
names.Add("字幕");
|
||||||
|
names.Add("工具");
|
||||||
|
|
||||||
|
// 插入(指定位置)
|
||||||
|
names.Insert(1, "新插入");
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
names.Remove("字幕");
|
||||||
|
names.RemoveAt(0); // 按索引删除
|
||||||
|
|
||||||
|
// 访问
|
||||||
|
string first = names[0];
|
||||||
|
|
||||||
|
// 数量
|
||||||
|
int count = names.Count;
|
||||||
|
|
||||||
|
// 遍历
|
||||||
|
foreach (string name in names)
|
||||||
|
{
|
||||||
|
Console.WriteLine(name);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 初始化器
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 声明时直接填充
|
||||||
|
List<string> fruits = new List<string>()
|
||||||
|
{
|
||||||
|
"苹果", "香蕉", "橙子"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 简写(C# 12+)
|
||||||
|
List<string> fruits2 = ["苹果", "香蕉", "橙子"];
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常用方法
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
List<int> numbers = new List<int>() { 3, 1, 4, 1, 5 };
|
||||||
|
|
||||||
|
numbers.Sort(); // 排序
|
||||||
|
numbers.Reverse(); // 反转
|
||||||
|
numbers.Contains(5); // 是否包含
|
||||||
|
numbers.IndexOf(4); // 查找索引
|
||||||
|
numbers.Clear(); // 清空
|
||||||
|
numbers.InsertRange(0, ...); // 插入集合
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dictionary<K, V> 键值对
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
// 声明
|
||||||
|
Dictionary<string, int> scores = new Dictionary<string, int>();
|
||||||
|
|
||||||
|
// 添加
|
||||||
|
scores["无言势"] = 100;
|
||||||
|
scores["玩家A"] = 85;
|
||||||
|
scores.Add("玩家B", 90);
|
||||||
|
|
||||||
|
// 访问
|
||||||
|
int score = scores["无言势"]; // 100
|
||||||
|
|
||||||
|
// 安全访问(键不存在不报错)
|
||||||
|
scores.TryGetValue("不存在", out int value);
|
||||||
|
|
||||||
|
// 是否包含键
|
||||||
|
if (scores.ContainsKey("无言势"))
|
||||||
|
{
|
||||||
|
Console.WriteLine(scores["无言势"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
scores.Remove("玩家A");
|
||||||
|
|
||||||
|
// 遍历
|
||||||
|
foreach (KeyValuePair<string, int> kv in scores)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{kv.Key}: {kv.Value}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只遍历键或值
|
||||||
|
foreach (string key in scores.Keys) { }
|
||||||
|
foreach (int value in scores.Values) { }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dictionary 初始化
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// C# 6+
|
||||||
|
Dictionary<string, int> config = new Dictionary<string, int>()
|
||||||
|
{
|
||||||
|
["sensitivity"] = 70,
|
||||||
|
["volume"] = 80,
|
||||||
|
["language"] = 1
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## List 和 Dictionary 在项目中的应用
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 识别结果历史
|
||||||
|
List<string> transcriptHistory = new List<string>();
|
||||||
|
|
||||||
|
// 设备配置
|
||||||
|
Dictionary<string, string> deviceConfig = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
["name"] = "USB麦克风",
|
||||||
|
["sampleRate"] = "16000",
|
||||||
|
["channels"] = "1"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 设置选项
|
||||||
|
Dictionary<string, bool> settings = new Dictionary<string, bool>()
|
||||||
|
{
|
||||||
|
["autoConnect"] = true,
|
||||||
|
["vad"] = true
|
||||||
|
};
|
||||||
|
```
|
||||||
164
notes/08_Exception_Handling.md
Normal file
164
notes/08_Exception_Handling.md
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
# 第八课:异常处理
|
||||||
|
|
||||||
|
## 什么是异常
|
||||||
|
|
||||||
|
异常 = 程序运行时的错误,导致程序无法正常继续。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
int[] numbers = { 1, 2, 3 };
|
||||||
|
int x = numbers[10]; // 索引越界 → 抛出 IndexOutOfRangeException
|
||||||
|
```
|
||||||
|
|
||||||
|
## try / catch / finally
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 可能出错的代码放这里
|
||||||
|
int[] numbers = { 1, 2, 3 };
|
||||||
|
int x = numbers[10];
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// 捕获异常并处理
|
||||||
|
Console.WriteLine($"出错了: {ex.Message}");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// 无论是否出错,都会执行(通常放清理代码)
|
||||||
|
Console.WriteLine("无论怎样都会执行");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 捕获特定异常类型
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int a = int.Parse("abc"); // 格式错误
|
||||||
|
}
|
||||||
|
catch (FormatException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("格式错误");
|
||||||
|
}
|
||||||
|
catch (OverflowException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("数字溢出");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"未知错误: {ex.Message}");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见异常类型
|
||||||
|
|
||||||
|
| 异常类型 | 触发场景 |
|
||||||
|
|----------|----------|
|
||||||
|
| `FormatException` | 格式错误(`int.Parse("abc")`) |
|
||||||
|
| `NullReferenceException` | 空对象访问(`obj.Method()`,`obj` 为 null) |
|
||||||
|
| `IndexOutOfRangeException` | 数组越界 |
|
||||||
|
| `FileNotFoundException` | 文件不存在 |
|
||||||
|
| `DivideByZeroException` | 除数为零 |
|
||||||
|
| `InvalidOperationException` | 操作无效状态 |
|
||||||
|
|
||||||
|
## throw 抛出异常
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
static void SetAge(int age)
|
||||||
|
{
|
||||||
|
if (age < 0 || age > 150)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("年龄必须在 0-150 之间");
|
||||||
|
}
|
||||||
|
Console.WriteLine($"年龄设置为: {age}");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetAge(-5);
|
||||||
|
}
|
||||||
|
catch (ArgumentException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"参数错误: {ex.Message}");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 自定义异常
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
class MicrophoneException : Exception
|
||||||
|
{
|
||||||
|
public MicrophoneException(string message) : base(message) { }
|
||||||
|
public MicrophoneException(string message, Exception inner) : base(message, inner) { }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## finally 的作用
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
FileStream file = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
file = new FileStream("test.txt", FileMode.Open);
|
||||||
|
// 读取文件...
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("文件不存在");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// 确保文件被关闭
|
||||||
|
file?.Close();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## using 语句(更简洁)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// using 自动释放资源(相当于 try-finally)
|
||||||
|
using (FileStream file = new FileStream("test.txt", FileMode.Open))
|
||||||
|
{
|
||||||
|
// 使用 file
|
||||||
|
} // 作用域结束后自动 Close()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 实际项目应用
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 尝试连接麦克风
|
||||||
|
microphone.Connect();
|
||||||
|
}
|
||||||
|
catch (DeviceNotFoundException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("麦克风未找到,请检查连接");
|
||||||
|
ShowReconnectDialog();
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("没有权限访问麦克风");
|
||||||
|
RequestPermission();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"未知错误: {ex.Message}");
|
||||||
|
LogError(ex);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 不要过度捕获异常
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// ✗ 不好:捕获所有异常但不处理
|
||||||
|
try { DoSomething(); }
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
// ✓ 好:只捕获能处理的异常
|
||||||
|
try { Connect(); }
|
||||||
|
catch (DeviceNotFoundException ex) { ShowError(); }
|
||||||
|
```
|
||||||
150
notes/09_File_IO.md
Normal file
150
notes/09_File_IO.md
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
# 第九课:文件读写
|
||||||
|
|
||||||
|
## 基本文件操作
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
// 写入文本
|
||||||
|
File.WriteAllText("test.txt", "你好,无言势字幕");
|
||||||
|
|
||||||
|
// 读取文本
|
||||||
|
string content = File.ReadAllText("test.txt");
|
||||||
|
```
|
||||||
|
|
||||||
|
## 路径操作
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 路径拼接
|
||||||
|
string path = Path.Combine("C:", "Users", "test", "config.json");
|
||||||
|
|
||||||
|
// 获取扩展名
|
||||||
|
string ext = Path.GetExtension("test.txt"); // ".txt"
|
||||||
|
|
||||||
|
// 获取文件名
|
||||||
|
string name = Path.GetFileName("C:/test/test.txt"); // "test.txt"
|
||||||
|
|
||||||
|
// 判断文件是否存在
|
||||||
|
bool exists = File.Exists("config.json");
|
||||||
|
```
|
||||||
|
|
||||||
|
## 读取文件
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 方式1:一次性读取(适合小文件)
|
||||||
|
string content = File.ReadAllText("test.txt");
|
||||||
|
|
||||||
|
// 方式2:按行读取
|
||||||
|
string[] lines = File.ReadAllLines("test.txt");
|
||||||
|
foreach (string line in lines)
|
||||||
|
{
|
||||||
|
Console.WriteLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方式3:流式读取(大文件)
|
||||||
|
using (StreamReader reader = new StreamReader("test.txt"))
|
||||||
|
{
|
||||||
|
while (!reader.EndOfStream)
|
||||||
|
{
|
||||||
|
string line = reader.ReadLine();
|
||||||
|
Console.WriteLine(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 写入文件
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 方式1:一次性写入
|
||||||
|
File.WriteAllText("output.txt", "内容");
|
||||||
|
|
||||||
|
// 方式2:按行写入
|
||||||
|
string[] lines = { "第一行", "第二行", "第三行" };
|
||||||
|
File.WriteAllLines("output.txt", lines);
|
||||||
|
|
||||||
|
// 方式3:追加内容
|
||||||
|
File.AppendAllText("log.txt", "新追加的内容\n");
|
||||||
|
|
||||||
|
// 方式4:流式写入
|
||||||
|
using (StreamWriter writer = new StreamWriter("output.txt"))
|
||||||
|
{
|
||||||
|
writer.WriteLine("第一行");
|
||||||
|
writer.WriteLine("第二行");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## JSON 序列化
|
||||||
|
|
||||||
|
.NET 内置 JSON 支持(System.Text.Json):
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
// 序列化(对象 -> JSON)
|
||||||
|
class Person
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Age { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
Person p = new Person { Name = "无言势", Age = 25 };
|
||||||
|
string json = JsonSerializer.Serialize(p);
|
||||||
|
Console.WriteLine(json);
|
||||||
|
// 输出: {"Name":"无言势","Age":25}
|
||||||
|
|
||||||
|
// 反序列化(JSON -> 对象)
|
||||||
|
string jsonStr = "{\"Name\":\"玩家A\",\"Age\":30}";
|
||||||
|
Person p2 = JsonSerializer.Deserialize<Person>(jsonStr);
|
||||||
|
Console.WriteLine(p2.Name); // "玩家A"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 配置文件示例
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// AppSettings 类
|
||||||
|
class AppSettings
|
||||||
|
{
|
||||||
|
public int Sensitivity { get; set; } = 70;
|
||||||
|
public bool AutoConnect { get; set; } = true;
|
||||||
|
public bool VadEnabled { get; set; } = true;
|
||||||
|
public string Language { get; set; } = "zh-CN";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存配置
|
||||||
|
AppSettings settings = new AppSettings();
|
||||||
|
string json = JsonSerializer.Serialize(settings, new JsonSerializerOptions { WriteIndented = true });
|
||||||
|
File.WriteAllText("config.json", json);
|
||||||
|
|
||||||
|
// 读取配置
|
||||||
|
string loaded = File.ReadAllText("config.json");
|
||||||
|
AppSettings loadedSettings = JsonSerializer.Deserialize<AppSettings>(loaded);
|
||||||
|
```
|
||||||
|
|
||||||
|
## using 语句自动关闭
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// StreamReader/Writer 必须关闭,否则文件被锁定
|
||||||
|
using (StreamReader reader = new StreamReader("test.txt"))
|
||||||
|
{
|
||||||
|
string line = reader.ReadLine();
|
||||||
|
}
|
||||||
|
// 作用域结束后自动 Close()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见错误处理
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string content = File.ReadAllText("notexist.txt");
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException)
|
||||||
|
{
|
||||||
|
Console.WriteLine("文件不存在");
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"IO错误: {ex.Message}");
|
||||||
|
}
|
||||||
|
```
|
||||||
182
notes/10_Delegates_and_Events.md
Normal file
182
notes/10_Delegates_and_Events.md
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
# 第十课:委托和事件
|
||||||
|
|
||||||
|
## 委托(Delegate)是什么
|
||||||
|
|
||||||
|
委托 = 函数的"容器",可以把函数当作变量传递。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 声明委托类型
|
||||||
|
delegate int Calculator(int a, int b);
|
||||||
|
|
||||||
|
// 定义符合委托的方法
|
||||||
|
int Add(int a, int b) => a + b;
|
||||||
|
int Multiply(int a, int b) => a * b;
|
||||||
|
|
||||||
|
// 使用委托
|
||||||
|
Calculator calc = Add;
|
||||||
|
int result = calc(1, 2); // result = 3
|
||||||
|
|
||||||
|
calc = Multiply;
|
||||||
|
result = calc(3, 4); // result = 12
|
||||||
|
```
|
||||||
|
|
||||||
|
## 为什么需要委托
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 场景:数组遍历时对每个元素做操作
|
||||||
|
void ProcessNumbers(int[] numbers, ??? operation)
|
||||||
|
{
|
||||||
|
foreach (int n in numbers)
|
||||||
|
{
|
||||||
|
??? result = operation(n);
|
||||||
|
Console.WriteLine(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 没有委托,你需要写多个重载
|
||||||
|
// 有委托,可以传任意操作
|
||||||
|
ProcessNumbers(nums, x => x * 2); // 翻倍
|
||||||
|
ProcessNumbers(nums, x => x + 1); // +1
|
||||||
|
ProcessNumbers(nums, x => x * x); // 平方
|
||||||
|
```
|
||||||
|
|
||||||
|
## Action 和 Func(简化委托)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Action: 返回 void 的委托
|
||||||
|
Action<string> print = (msg) => Console.WriteLine(msg);
|
||||||
|
print("Hello"); // 无返回值
|
||||||
|
|
||||||
|
// Func: 有返回值的委托
|
||||||
|
Func<int, int, int> add = (a, b) => a + b;
|
||||||
|
int result = add(1, 2); // 3
|
||||||
|
|
||||||
|
// 多参数
|
||||||
|
Func<string, string, string> concat = (a, b) => a + b;
|
||||||
|
string s = concat("Hello", " World"); // "Hello World"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 事件(Event)是什么
|
||||||
|
|
||||||
|
事件 = 委托的升级版,只能 += 添加监听,不能外部直接调用。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
class Button
|
||||||
|
{
|
||||||
|
// 事件声明
|
||||||
|
public event Action Clicked;
|
||||||
|
|
||||||
|
public void OnClick()
|
||||||
|
{
|
||||||
|
Console.WriteLine("按钮被点击");
|
||||||
|
// 触发事件(只能在类内部)
|
||||||
|
Clicked?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 使用事件
|
||||||
|
Button btn = new Button();
|
||||||
|
|
||||||
|
// 添加监听者
|
||||||
|
btn.Clicked += () => Console.WriteLine("Handler 1 执行");
|
||||||
|
btn.Clicked += () => Console.WriteLine("Handler 2 执行");
|
||||||
|
|
||||||
|
btn.OnClick();
|
||||||
|
// 输出:
|
||||||
|
// 按钮被点击
|
||||||
|
// Handler 1 执行
|
||||||
|
// Handler 2 执行
|
||||||
|
```
|
||||||
|
|
||||||
|
## 事件 + 委托的应用场景
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
class Microphone
|
||||||
|
{
|
||||||
|
// 事件声明
|
||||||
|
public event Action<string> OnTranscriptReady; // 识别出文字时触发
|
||||||
|
public event Action OnListeningStarted;
|
||||||
|
public event Action OnListeningStopped;
|
||||||
|
|
||||||
|
private bool isListening;
|
||||||
|
|
||||||
|
public void StartListening()
|
||||||
|
{
|
||||||
|
isListening = true;
|
||||||
|
Console.WriteLine("麦克风开始监听...");
|
||||||
|
OnListeningStarted?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopListening()
|
||||||
|
{
|
||||||
|
isListening = false;
|
||||||
|
Console.WriteLine("麦克风停止监听...");
|
||||||
|
OnListeningStopped?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟识别到文字
|
||||||
|
public void TranscriptDetected(string text)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"识别到: {text}");
|
||||||
|
OnTranscriptReady?.Invoke(text); // 触发事件,通知所有监听者
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 使用
|
||||||
|
Microphone mic = new Microphone();
|
||||||
|
|
||||||
|
// 订阅事件
|
||||||
|
mic.OnTranscriptReady += (text) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"收到文字: {text}");
|
||||||
|
};
|
||||||
|
|
||||||
|
mic.OnListeningStarted += () =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("开始记录...");
|
||||||
|
};
|
||||||
|
|
||||||
|
mic.OnListeningStopped += () =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("停止记录");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 触发
|
||||||
|
mic.StartListening();
|
||||||
|
mic.TranscriptDetected("今天天气不错");
|
||||||
|
mic.TranscriptDetected("大家一起加油");
|
||||||
|
mic.StopListening();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 事件 vs 委托
|
||||||
|
|
||||||
|
| | 委托 | 事件 |
|
||||||
|
|---|---|---|
|
||||||
|
| 外部添加监听 | ✓ | ✓ |
|
||||||
|
| 外部调用 | ✓ | ✗ |
|
||||||
|
| 主要用途 | 传递函数 | 通知机制 |
|
||||||
|
|
||||||
|
## 移除监听
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
Action handler = () => Console.WriteLine("Handler");
|
||||||
|
|
||||||
|
btn.Clicked += handler;
|
||||||
|
btn.Clicked -= handler; // 移除
|
||||||
|
```
|
||||||
|
|
||||||
|
## 实际项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
语音识别服务
|
||||||
|
├── OnTranscriptReady(text) → UI 更新文字
|
||||||
|
├── OnListeningStarted() → UI 显示监听状态
|
||||||
|
├── OnListeningStopped() → UI 停止动画
|
||||||
|
└── OnError(error) → UI 显示错误
|
||||||
|
```
|
||||||
|
|
||||||
|
事件让各部分解耦,不需要互相引用。
|
||||||
121
notes/11_WebView2_Basics.md
Normal file
121
notes/11_WebView2_Basics.md
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
# WebView2 入门
|
||||||
|
|
||||||
|
## 什么是 WebView2
|
||||||
|
|
||||||
|
在 Windows 桌面应用里嵌入 Chrome 内核浏览器。
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────┐
|
||||||
|
│ WPF / WinForms │
|
||||||
|
│ ┌───────────────────┐ │
|
||||||
|
│ │ WebView2 │ │
|
||||||
|
│ │ (Chrome 内核) │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ ┌─────────────┐ │ │
|
||||||
|
│ │ │ HTML/CSS/JS │ │ │
|
||||||
|
│ │ │ 你的界面 │ │ │
|
||||||
|
│ │ └─────────────┘ │ │
|
||||||
|
│ └───────────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ C# 代码 │
|
||||||
|
└─────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 安装 WebView2 Runtime
|
||||||
|
|
||||||
|
下载地址:https://developer.microsoft.com/en-us/microsoft-edge/webview2/
|
||||||
|
|
||||||
|
## NuGet 包
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet add package Microsoft.Web.WebView2
|
||||||
|
```
|
||||||
|
|
||||||
|
## XAML 使用
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<Window xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf">
|
||||||
|
<Grid>
|
||||||
|
<wv2:WebView2 x:Name="WebView"
|
||||||
|
Source="https://example.com"/>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 初始化
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private async void InitializeWebView()
|
||||||
|
{
|
||||||
|
await WebView.EnsureCoreWebView2Async();
|
||||||
|
Console.WriteLine("WebView2 初始化成功");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## C# 调用 JS
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 执行 JS
|
||||||
|
await WebView.ExecuteScriptAsync("alert('Hello from C#')");
|
||||||
|
|
||||||
|
// 获取返回值
|
||||||
|
string result = await WebView.ExecuteScriptAsync("document.title");
|
||||||
|
```
|
||||||
|
|
||||||
|
## JS 调用 C#
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// C# 注册方法
|
||||||
|
WebView.CoreWebView2.WebMessageReceived += (s, e) =>
|
||||||
|
{
|
||||||
|
string message = e.TryGetWebMessageAsString();
|
||||||
|
Console.WriteLine($"收到JS消息: {message}");
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// JS 发送消息
|
||||||
|
window.chrome.webview.postMessage("Hello from JS");
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常用操作
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
WebView.Reload(); // 刷新
|
||||||
|
WebView.GoBack(); // 后退
|
||||||
|
WebView.GoForward(); // 前进
|
||||||
|
WebView.Navigate("https://..."); // 导航到 URL
|
||||||
|
WebView.CoreWebView2.Settings // 配置
|
||||||
|
```
|
||||||
|
|
||||||
|
## 本地 HTML
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 加载本地 HTML 文件
|
||||||
|
string htmlPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "index.html");
|
||||||
|
WebView.CoreWebView2.Navigate(new Uri(htmlPath).AbsoluteUri);
|
||||||
|
|
||||||
|
// 或者直接加载 HTML 字符串
|
||||||
|
string html = "<h1>Hello</h1>";
|
||||||
|
WebView.NavigateToString(html);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 项目里怎么用
|
||||||
|
|
||||||
|
```
|
||||||
|
无言势字幕/
|
||||||
|
├── MainWindow.xaml ← WPF 窗口,放 WebView2
|
||||||
|
├── index.html ← 你的界面(HTML/CSS/JS)
|
||||||
|
├── WebViewManager.cs ← C# 和 JS 通信
|
||||||
|
└── AsrService.cs ← 语音识别服务
|
||||||
|
```
|
||||||
|
|
||||||
|
C# 负责:
|
||||||
|
- 语音识别(Sherpa-ONNX)
|
||||||
|
- OSC 发送
|
||||||
|
- 窗口管理
|
||||||
|
|
||||||
|
HTML/JS 负责:
|
||||||
|
- 界面显示
|
||||||
|
- 动画效果
|
||||||
|
- 用户交互
|
||||||
BIN
notes/PDF/01_CSharp_Basics.pdf
Normal file
BIN
notes/PDF/01_CSharp_Basics.pdf
Normal file
Binary file not shown.
BIN
notes/PDF/02_Variables_and_Types.pdf
Normal file
BIN
notes/PDF/02_Variables_and_Types.pdf
Normal file
Binary file not shown.
BIN
notes/PDF/03_Conditions_and_Loops.pdf
Normal file
BIN
notes/PDF/03_Conditions_and_Loops.pdf
Normal file
Binary file not shown.
BIN
notes/PDF/04_Methods_and_Classes.pdf
Normal file
BIN
notes/PDF/04_Methods_and_Classes.pdf
Normal file
Binary file not shown.
BIN
notes/PDF/05_MultiFile_and_Access_Modifiers.pdf
Normal file
BIN
notes/PDF/05_MultiFile_and_Access_Modifiers.pdf
Normal file
Binary file not shown.
BIN
notes/PDF/06_Inheritance_and_Interface.pdf
Normal file
BIN
notes/PDF/06_Inheritance_and_Interface.pdf
Normal file
Binary file not shown.
BIN
notes/PDF/07_Collections.pdf
Normal file
BIN
notes/PDF/07_Collections.pdf
Normal file
Binary file not shown.
BIN
notes/PDF/08_Exception_Handling.pdf
Normal file
BIN
notes/PDF/08_Exception_Handling.pdf
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user