C#编程(进阶)知识汇总

C# 编程进阶详细讲解

1. C# 简介、VS 工具安装及使用

1.1 C# 语言概述

C#(发音为 C-Sharp)是微软开发的一种现代、面向对象的编程语言,它属于 .NET 平台的核心语言之一。C# 结合了 C++ 的强大功能和 Visual Basic 的易用性,语法简洁且类型安全。

C# 的主要特点:

  • 面向对象:支持类、继承、多态等特性
  • 类型安全:编译时进行严格的类型检查
  • 组件导向:支持组件的定义、实现和使用
  • 自动内存管理:通过垃圾回收机制自动管理内存
  • 与 .NET 框架紧密集成:可以访问 .NET 提供的丰富类库

C# 的应用场景:

  • 桌面应用程序开发
  • Web 应用程序开发(ASP.NET
  • 移动应用开发(Xamarin)
  • 游戏开发(Unity 引擎)
  • 云服务和微服务
  • 物联网应用

1.2 Visual Studio 工具安装

Visual Studio 是微软提供的集成开发环境(IDE),专门用于开发 C# 和其他 .NET 语言的应用程序。安装步骤如下:

  1. 访问 Visual Studio 官方下载页面
  2. 选择适合您需求的版本(社区版、专业版或企业版)
  3. 运行安装程序,选择所需的工作负载:
    • 对于 C# 开发,建议选择 ".NET 桌面开发" 和 "ASP.NET 和 Web 开发 "
    • 如果计划进行移动开发,还可以选择 "使用 .NET 的移动开发"
  4. 选择要安装的可选组件(如测试工具、版本控制等)
  5. 点击安装,等待安装完成

安装完成后,可以通过开始菜单启动 Visual Studio。首次启动时,系统会要求您选择开发设置和主题。

1.3 解决方案与项目模板

在 Visual Studio 中,解决方案(Solution)是项目的容器,一个解决方案可以包含多个相关的项目。项目(Project)则是应用程序的基本构建块,包含了源代码、资源文件和配置信息。

创建新项目的步骤:

  1. 启动 Visual Studio
  2. 选择 "创建新项目"
  3. 在搜索框中输入所需的项目模板类型(如 "控制台应用"、"Windows 窗体应用" 等)
  4. 选择适合的项目模板,点击 "下一步"
  5. 设置项目名称和位置,点击 "创建"

常见的 C# 项目模板:

  • 控制台应用程序:用于创建命令行界面的应用程序
  • Windows 窗体应用程序:用于创建 Windows 桌面应用程序
  • WPF 应用程序:用于创建现代 Windows 桌面应用程序
  • ASP.NET Web 应用程序:用于创建 Web 应用程序
  • 类库:用于创建可重用的代码库
  • Xamarin 应用程序:用于创建跨平台移动应用

1.4 编译过程及原理

C# 程序的编译过程涉及多个步骤:

  1. 源代码编译:C# 源代码(.cs 文件)被 C# 编译器(csc.exe)编译为中间语言(IL,Intermediate Language)代码,存储在程序集(.dll 或 .exe 文件)中。

  2. 程序集生成:编译后的 IL 代码与元数据(描述类型和成员信息)一起打包到程序集中。程序集是 .NET 应用程序的部署单元。

  3. JIT 编译:当程序运行时,.NET 运行时(CLR,Common Language Runtime)使用即时编译器(JIT,Just-In-Time Compiler)将 IL 代码转换为机器码,以便 CPU 执行。

  4. 垃圾回收:CLR 负责管理内存,通过垃圾回收机制自动回收不再使用的对象所占用的内存。

C# 编译过程的优势:

  • 跨平台性:IL 代码可以在任何支持 .NET 运行时的平台上执行
  • 安全性:元数据提供了类型信息,增强了类型安全性
  • 性能优化:JIT 编译可以根据运行时环境进行优化

2. 控制台程序基础

2.1 控制台程序结构

控制台程序是最简单的 C# 应用程序类型,它通过命令行界面与用户交互。一个基本的 C# 控制台程序结构如下:

csharp

using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            // 程序入口点
            Console.WriteLine("Hello, World!");
            Console.ReadLine(); // 等待用户输入,防止窗口立即关闭
        }
    }
}

程序结构说明:

  • using System;:引入 System 命名空间,该命名空间包含了许多常用的类型和功能
  • namespace HelloWorld:定义命名空间,用于组织代码
  • class Program:定义一个名为 Program 的类
  • static void Main(string[] args):程序的入口点方法,程序从这里开始执行
  • Console.WriteLine():向控制台输出一行文本
  • Console.ReadLine():从控制台读取一行输入

2.2 Main 方法详解

Main 方法是 C# 程序的入口点,它具有以下特点:

  • 必须是静态方法(static)
  • 返回类型可以是 void 或 int
  • 可以接受一个字符串数组作为参数(string [] args),用于接收命令行参数

Main 方法的四种合法形式:

csharp

// 形式 1:无返回值,无参数
static void Main()
{
    // 代码
}

// 形式 2:无返回值,带参数
static void Main(string[] args)
{
    // 代码
}

// 形式 3:返回 int,无参数
static int Main()
{
    // 代码
    return 0; // 返回退出代码
}

// 形式 4:返回 int,带参数
static int Main(string[] args)
{
    // 代码
    return 0; // 返回退出代码
}

当 Main 方法返回 int 时,返回值通常用作程序的退出代码。退出代码 0 表示程序正常结束,非零值表示有错误发生。

2.3 Console 类使用

Console 类提供了与控制台进行交互的方法,主要包括输入输出功能。

常用的 Console 类方法:

csharp

// 输出方法
Console.WriteLine("Hello, World!"); // 输出一行文本并换行
Console.Write("Enter your name: "); // 输出文本但不换行

// 输入方法
string name = Console.ReadLine(); // 读取一行输入
int number = int.Parse(Console.ReadLine()); // 读取整数输入

// 颜色控制
Console.ForegroundColor = ConsoleColor.Red; // 设置文本颜色
Console.WriteLine("This text is red.");
Console.ResetColor(); // 恢复默认颜色

// 其他
Console.Beep(); // 发出蜂鸣声
Console.Clear(); // 清屏

2.4 注释与命名空间

注释

C# 支持三种类型的注释:

csharp

// 单行注释:用于注释单行代码

/*
多行注释:
用于注释多行代码
*/

/// <summary>
/// XML 注释:用于为类型和成员提供文档说明
/// 通常用于自动生成 API 文档
/// </summary>
public class MyClass
{
    /// <summary>
    /// 计算两个整数的和
    /// </summary>
    /// <param name="a">第一个整数</param>
    /// <param name="b">第二个整数</param>
    /// <returns>两个整数的和</returns>
    public int Add(int a, int b)
    {
        return a + b;
    }
}
命名空间

命名空间用于组织代码,避免命名冲突。可以使用 using 关键字引入其他命名空间,从而无需每次都使用完全限定名。

csharp

using System; // 引入 System 命名空间
using System.IO; // 引入 System.IO 命名空间

namespace MyNamespace
{
    class Program
    {
        static void Main()
        {
            // 使用 System 命名空间中的 Console 类
            Console.WriteLine("Hello, World!");
            
            // 使用 System.IO 命名空间中的 File 类
            File.WriteAllText("test.txt", "Hello, File!");
        }
    }
}

2.5 Debug 调试技巧

在开发过程中,调试是解决问题的重要手段。Visual Studio 提供了强大的调试功能:

  1. 设置断点:在代码行左侧单击,设置断点。程序执行到断点时会暂停,允许您检查变量和执行状态。

  2. 单步执行

    • F10逐过程执行(跳过方法内部)
    • F11逐语句执行(进入方法内部)
    • Shift+F11:跳出当前方法
  3. 检查变量

    • 鼠标悬停在变量上查看其值
    • 使用 "局部变量" 窗口查看当前作用域内的所有变量
    • 使用 "监视" 窗口跟踪特定变量的变化
  4. 调试输出:使用 System.Diagnostics.Debug.WriteLine() 输出调试信息

  5. 条件断点:右键单击断点,设置条件,只有当条件满足时断点才会触发

  6. 异常捕获:使用 "异常设置" 窗口指定要捕获的异常类型

调试示例:

csharp

using System;

namespace DebugExample
{
    class Program
    {
        static void Main(string[] args)
        {
            int a = 10;
            int b = 0;
            
            // 设置断点在此行
            int result = Divide(a, b);
            Console.WriteLine($"Result: {result}");
        }
        
        static int Divide(int x, int y)
        {
            // 预期会发生除零异常
            return x / y;
        }
    }
}

3. 数据类型与异常处理

3.1 值类型与引用类型

在 C# 中,数据类型分为两大类:值类型引用类型

值类型(Value Types)

值类型变量直接存储数据的值,它们分配在栈上(或作为字段嵌入在对象中)。值类型包括:

  • 简单类型:整数(int, long, short 等)、浮点数(float, double)、布尔值(bool)、字符(char)
  • 枚举类型(enum)
  • 结构类型(struct)
  • 可空值类型(Nullable<T>)

csharp

int num = 42; // 值类型,直接存储 42
bool isTrue = true;
char letter = 'A';
引用类型(Reference Types)

引用类型变量存储对数据的引用(内存地址),而不是数据本身。引用类型分配在堆上,通过垃圾回收自动管理内存。引用类型包括:

  • 类(class)
  • 接口(interface)
  • 数组(array)
  • 委托(delegate)
  • 字符串(string)

csharp

string message = "Hello"; // 引用类型,存储对字符串对象的引用
int[] numbers = new int[5]; // 数组也是引用类型
值类型与引用类型的主要区别
特性值类型引用类型
存储方式直接存储值存储对对象的引用
内存位置栈或嵌入在对象中
默认值0, false, null 等null
复制方式复制值复制引用
实例创建无需使用 new 关键字必须使用 new 关键字
继承不支持继承(除了从 System.ValueType 继承)支持继承

3.2 可空类型

可空类型允许值类型变量存储 null 值,这在处理可能没有值的情况下非常有用。可空类型通过在值类型后加问号(?)来声明,实际上是 System.Nullable<T> 结构的简写。

csharp

int? nullableInt = null; // 可空 int 类型
DateTime? nullableDate = null; // 可空 DateTime 类型

// 使用可空类型
if (nullableInt.HasValue)
{
    Console.WriteLine($"Value: {nullableInt.Value}");
}
else
{
    Console.WriteLine("No value");
}

// 空合并运算符(??)
int value = nullableInt ?? 0; // 如果 nullableInt 为 null,则使用 0

3.3 变量与常量

变量

变量是存储数据的容器,必须先声明后使用。变量声明时需要指定类型,也可以使用 var 关键字让编译器自动推断类型。

csharp

// 显式类型声明
int age = 30;
string name = "John";
double salary = 5000.50;

// 隐式类型声明(使用 var)
var number = 100; // 编译器推断为 int
var message = "Hello"; // 编译器推断为 string
常量

常量是在编译时初始化且不能修改的值,使用 const 关键字声明。常量必须在声明时赋值,并且值必须是编译时常量表达式。

csharp

const double PI = 3.14159;
const string COMPANY_NAME = "ABC Inc.";

// 错误:常量必须在声明时赋值
// const int x; 
// x = 10;

// 正确:编译时常量表达式
const int MAX_VALUE = 100 * 2;

3.4 C# 关键字与类型转换

C# 关键字

C# 有许多保留关键字,这些关键字不能用作标识符(如变量名、类名等),除非使用 @ 前缀。

常见的 C# 关键字:

  • 数据类型:int, string, bool, double, char, class, struct, enum 等
  • 控制流:if, else, switch, case, for, while, do, foreach 等
  • 访问修饰符:public, private, protected, internal 等
  • 其他:static, virtual, override, abstract, sealed, try, catch, finally 等
类型转换

类型转换是将一种数据类型转换为另一种数据类型的过程。C# 支持两种类型的转换:

  1. 隐式转换:编译器自动进行的转换,不会丢失数据。通常是从较小的类型转换为较大的类型。

csharp

int a = 10;
long b = a; // 隐式转换:int -> long

  1. 显式转换(强制转换):需要使用强制转换运算符 (type),可能会丢失数据。

csharp

double d = 3.14;
int i = (int)d; // 显式转换:double -> int,结果为 3

  1. 类型转换方法:使用 Convert 类或类型的 Parse/TryParse 方法。

csharp

string s = "123";
int num = int.Parse(s); // 字符串转整数

// 安全转换,避免异常
if (int.TryParse(s, out num))
{
    Console.WriteLine($"Parsed: {num}");
}
else
{
    Console.WriteLine("Invalid number");
}

// 使用 Convert 类
double d = 3.14;
int i = Convert.ToInt32(d); // 3

3.5 异常处理机制

异常是程序执行期间发生的错误。C# 提供了结构化的异常处理机制,使用 try-catch-finally 块来捕获和处理异常。

csharp

try
{
    // 可能会抛出异常的代码
    int result = Divide(10, 0); // 会抛出 DivideByZeroException
    Console.WriteLine($"Result: {result}");
}
catch (DivideByZeroException ex)
{
    // 处理特定类型的异常
    Console.WriteLine($"Error: {ex.Message}");
}
catch (Exception ex)
{
    // 处理其他类型的异常
    Console.WriteLine($"General error: {ex.Message}");
}
finally
{
    // 无论是否发生异常,都会执行的代码
    Console.WriteLine("This code always executes.");
}

static int Divide(int x, int y)
{
    if (y == 0)
    {
        throw new DivideByZeroException("除数不能为零"); // 抛出异常
    }
    return x / y;
}
自定义异常

可以通过继承 Exception 类来创建自定义异常:

csharp

public class CustomException : Exception
{
    public CustomException() : base() { }
    public CustomException(string message) : base(message) { }
    public CustomException(string message, Exception innerException) : base(message, innerException) { }
}
使用 throw 重新抛出异常

在 catch 块中处理部分异常后,可以使用 throw 重新抛出异常:

csharp

try
{
    // 代码
}
catch (Exception ex)
{
    // 记录日志
    Console.WriteLine($"Logging error: {ex.Message}");
    throw; // 重新抛出原始异常
}

4. 运算符详解

4.1 赋值运算符

赋值运算符用于给变量赋值,最基本的是 =,还有复合赋值运算符。

csharp

int a = 10; // 基本赋值
a += 5;     // 复合赋值,等价于 a = a + 5
a -= 3;     // 等价于 a = a - 3
a *= 2;     // 等价于 a = a * 2
a /= 4;     // 等价于 a = a / 4
a %= 3;     // 等价于 a = a % 3

4.2 算数运算符

算数运算符用于执行基本的数学运算。

csharp

int a = 10, b = 3;
int sum = a + b;      // 加法:13
int difference = a - b; // 减法:7
int product = a * b;  // 乘法:30
int quotient = a / b; // 除法:3(整数除法)
int remainder = a % b; // 取余:1

// 自增和自减
int x = 5;
int y = ++x; // 先自增,再赋值,y = 6, x = 6
y = x++;     // 先赋值,再自增,y = 6, x = 7
y = --x;     // 先自减,再赋值,y = 5, x = 5
y = x--;     // 先赋值,再自减,y = 5, x = 4

4.3 关系运算符

关系运算符用于比较两个值,返回布尔值。

csharp

int a = 10, b = 5;
bool result;

result = a > b;   // 大于:true
result = a < b;   // 小于:false
result = a >= b;  // 大于等于:true
result = a <= b;  // 小于等于:false
result = a == b;  // 等于:false
result = a != b;  // 不等于:true

4.4 逻辑运算符

逻辑运算符用于对布尔值进行逻辑操作。

csharp

bool x = true, y = false;
bool result;

result = x && y;  // 逻辑与:false(两个都为 true 才为 true)
result = x || y;  // 逻辑或:true(至少一个为 true 即为 true)
result = !x;      // 逻辑非:false
result = x ^ y;   // 逻辑异或:true(两个不同时为 true)

// 短路逻辑
bool a = false, b = true;
bool c = a && (b = false); // 由于 a 为 false,右侧表达式不会执行,b 仍为 true

4.5 位运算符

位运算符用于对整数类型的二进制位进行操作。

csharp

int a = 5;  // 二进制:0101
int b = 3;  // 二进制:0011
int result;

result = a & b;  // 按位与:0001 (1)
result = a | b;  // 按位或:0111 (7)
result = a ^ b;  // 按位异或:0110 (6)
result = ~a;     // 按位取反:1010 (-6,补码表示)
result = a << 2; // 左移两位:010100 (20)
result = a >> 1; // 右移一位:0010 (2)

4.6 三元运算符

三元运算符是一种简洁的条件表达式,语法为 condition ? value_if_true : value_if_false

csharp

int age = 18;
string message = age >= 18 ? "成年人" : "未成年人"; // "成年人"

// 嵌套三元运算符
int score = 85;
string grade = score >= 90 ? "A" : 
              (score >= 80 ? "B" : 
              (score >= 70 ? "C" : 
              (score >= 60 ? "D" : "F"))); // "B"

4.7 其他运算符

空条件运算符(?.)

用于在调用成员之前检查对象是否为 null,避免 NullReferenceException

csharp

string s = null;
int? length = s?.Length; // 如果 s 为 null,返回 null,否则返回 Length
空合并运算符(??)

用于提供默认值,当左侧操作数为 null 时返回右侧操作数。

csharp

string name = null;
string displayName = name ?? "未知"; // "未知"
类型检查运算符(is)

用于检查对象是否为特定类型。

csharp

object obj = "Hello";
bool isString = obj is string; // true
类型转换运算符(as)

尝试将对象转换为指定类型,如果转换失败则返回 null。

csharp

object obj = "Hello";
string s = obj as string; // 如果 obj 不是 string,返回 null

5. 数组与集合

5.1 数组基础与索引

数组是一种固定大小的、存储相同类型元素的连续内存块。数组可以通过索引访问,索引从 0 开始。

csharp

// 声明和初始化数组
int[] numbers = new int[5]; // 声明一个包含 5 个整数的数组
numbers[0] = 10; // 赋值给第一个元素
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;

// 另一种初始化方式
string[] names = new string[] { "Alice", "Bob", "Charlie" };

// 简化语法
int[] scores = { 85, 90, 78, 92, 88 };

// 访问数组元素
int firstNumber = numbers[0]; // 10
string secondName = names[1]; // "Bob"

5.2 数组遍历与排序

遍历数组的常见方法:

csharp

int[] numbers = { 10, 20, 30, 40, 50 };

// 使用 for 循环
for (int i = 0; i < numbers.Length; i++)
{
    Console.WriteLine(numbers[i]);
}

// 使用 foreach 循环
foreach (int number in numbers)
{
    Console.WriteLine(number);
}

// 使用 Lambda 表达式(需要转换为 IEnumerable<int>)
Array.ForEach(numbers, n => Console.WriteLine(n));

数组排序:

csharp

int[] unsorted = { 5, 3, 8, 1, 2 };
Array.Sort(unsorted); // 升序排序:1, 2, 3, 5, 8

// 降序排序
Array.Sort(unsorted);
Array.Reverse(unsorted); // 8, 5, 3, 2, 1

// 自定义排序(降序)
Array.Sort(unsorted, (a, b) => b.CompareTo(a)); // 8, 5, 3, 2, 1

5.3 一维数组

一维数组是最简单的数组形式,上面的例子都是一维数组。

csharp

// 声明和初始化一维数组
int[] numbers = new int[5]; // 包含 5 个元素的整数数组
string[] names = { "Alice", "Bob", "Charlie" }; // 包含 3 个元素的字符串数组

5.4 多维数组

多维数组是指数组的元素也是数组,可以有二维、三维等。

csharp

// 二维数组
int[,] matrix = new int[3, 4]; // 3 行 4 列的二维数组

// 初始化二维数组
int[,] table = {
    { 1, 2, 3 },
    { 4, 5, 6 },
    { 7, 8, 9 }
};

// 访问二维数组元素
int value = table[1, 2]; // 第二行第三列的元素,值为 6

// 遍历二维数组
for (int i = 0; i < table.GetLength(0); i++) // 行数
{
    for (int j = 0; j < table.GetLength(1); j++) // 列数
    {
        Console.Write(table[i, j] + " ");
    }
    Console.WriteLine();
}

5.5 交错数组

交错数组是数组的数组,每个子数组的长度可以不同。

csharp

// 声明交错数组
int[][] jaggedArray = new int[3][];

// 初始化每个子数组
jaggedArray[0] = new int[2]; // 第一个子数组有 2 个元素
jaggedArray[1] = new int[3]; // 第二个子数组有 3 个元素
jaggedArray[2] = new int[4]; // 第三个子数组有 4 个元素

// 赋值
jaggedArray[0][0] = 1;
jaggedArray[0][1] = 2;
jaggedArray[1][0] = 3;
jaggedArray[1][1] = 4;
jaggedArray[1][2] = 5;
// ...

// 另一种初始化方式
int[][] anotherJagged = new int[][] {
    new int[] { 1, 2 },
    new int[] { 3, 4, 5 },
    new int[] { 6, 7, 8, 9 }
};

// 简化语法
int[][] simpleJagged = {
    new int[] { 1, 2 },
    new int[] { 3, 4, 5 },
    new int[] { 6, 7, 8, 9 }
};

5.6 隐式类型化数组

隐式类型化数组使用 var 关键字声明,编译器会自动推断数组类型。

csharp

// 隐式类型化数组
var numbers = new[] { 10, 20, 30 }; // 推断为 int[]
var names = new[] { "Alice", "Bob", "Charlie" }; // 推断为 string[]

// 多维隐式类型化数组
var matrix = new[] {
    new[] { 1, 2 },
    new[] { 3, 4 }
}; // 推断为 int[][]

6. 面向对象编程基础

6.1 类与对象

类是对象的蓝图,定义了对象的属性和方法。对象是类的实例。

csharp

// 定义类
public class Person
{
    // 字段
    private string name;
    private int age;

    // 属性
    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public int Age
    {
        get { return age; }
        set { age = value; }
    }

    // 方法
    public void SayHello()
    {
        Console.WriteLine($"Hello, my name is {name} and I'm {age} years old.");
    }
}

// 创建对象
Person person = new Person();
person.Name = "John";
person.Age = 30;
person.SayHello(); // 输出:Hello, my name is John and I'm 30 years old.

6.2 属性与方法

属性

属性是一种特殊的成员,提供对类的字段的访问,通常包含 get 和 set 访问器。

csharp

public class Rectangle
{
    private double width;
    private double height;

    // 自动实现的属性
    public double Width { get; set; }
    public double Height { get; set; }

    // 计算属性
    public double Area
    {
        get { return Width * Height; }
    }

    // 带验证的属性
    public double Length
    {
        get { return length; }
        set
        {
            if (value < 0)
                throw new ArgumentException("Length cannot be negative");
            length = value;
        }
    }
}
方法

方法是类中定义的行为,包含一系列执行语句。

csharp

public class Calculator
{
    // 静态方法
    public static int Add(int a, int b)
    {
        return a + b;
    }

    // 实例方法
    public int Subtract(int a, int b)
    {
        return a - b;
    }
}

// 调用静态方法
int sum = Calculator.Add(10, 20);

// 调用实例方法
Calculator calc = new Calculator();
int difference = calc.Subtract(20, 10);

6.3 构造函数

构造函数是一种特殊的方法,用于初始化对象。构造函数的名称与类名相同,且没有返回类型。

csharp

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    // 默认构造函数
    public Person()
    {
        Name = "Unknown";
        Age = 0;
    }

    // 带参数的构造函数
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

// 创建对象
Person p1 = new Person(); // 使用默认构造函数
Person p2 = new Person("Alice", 25); // 使用带参数的构造函数

6.4 封装、继承与多态

封装

封装是将数据(字段)和操作数据的方法(属性和方法)绑定在一起,并隐藏对象的内部实现细节。通过访问修饰符(如 public、private)实现。

csharp

public class BankAccount
{
    private decimal balance; // 私有字段,外部无法直接访问

    public decimal Balance
    {
        get { return balance; }
        private set { balance = value; } // 只能在类内部修改
    }

    public void Deposit(decimal amount)
    {
        if (amount > 0)
            balance += amount;
    }

    public bool Withdraw(decimal amount)
    {
        if (amount <= balance)
        {
            balance -= amount;
            return true;
        }
        return false;
    }
}
继承

继承允许一个类(子类)继承另一个类(父类)的属性和方法,实现代码复用和层次化设计。

csharp

// 父类
public class Animal
{
    public string Name { get; set; }

    public Animal(string name)
    {
        Name = name;
    }

    public virtual void Speak()
    {
        Console.WriteLine($"{Name} makes a sound.");
    }
}

// 子类
public class Dog : Animal
{
    public Dog(string name) : base(name) { }

    public override void Speak()
    {
        Console.WriteLine($"{Name} barks.");
    }
}

// 使用继承
Animal animal = new Animal("Generic Animal");
animal.Speak(); // 输出:Generic Animal makes a sound.

Dog dog = new Dog("Buddy");
dog.Speak(); // 输出:Buddy barks.
多态

多态允许通过基类引用调用派生类的方法,实现运行时行为的动态绑定。

csharp

Animal animal1 = new Dog("Buddy");
Animal animal2 = new Cat("Whiskers");

animal1.Speak(); // 输出:Buddy barks.(动态绑定到 Dog 的 Speak 方法)
animal2.Speak(); // 输出:Whiskers meows.(动态绑定到 Cat 的 Speak 方法)

6.5 基类与子类

基类(父类)是被继承的类,子类(派生类)是继承基类的类。子类可以扩展基类的功能,也可以重写基类的方法。

csharp

// 基类
public class Vehicle
{
    public string Brand { get; set; }

    public virtual void Start()
    {
        Console.WriteLine("Vehicle started.");
    }
}

// 子类
public class Car : Vehicle
{
    public int NumberOfDoors { get; set; }

    public override void Start()
    {
        Console.WriteLine($"Car {Brand} started.");
    }
}

// 使用基类和子类
Vehicle vehicle = new Vehicle { Brand = "Generic Vehicle" };
vehicle.Start(); // 输出:Vehicle started.

Car car = new Car { Brand = "Toyota", NumberOfDoors = 4 };
car.Start(); // 输出:Car Toyota started.

7. 类的高级特性

7.1 部分类

部分类允许将一个类的定义分散到多个文件中,使用 partial 关键字声明。

csharp

// 文件1: Person.part1.cs
public partial class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public void SayHello()
    {
        Console.WriteLine($"Hello, my name is {Name}.");
    }
}

// 文件2: Person.part2.cs
public partial class Person
{
    public void SayGoodbye()
    {
        Console.WriteLine($"Goodbye from {Name}.");
    }
}

// 使用部分类
Person person = new Person { Name = "John" };
person.SayHello(); // 输出:Hello, my name is John.
person.SayGoodbye(); // 输出:Goodbye from John.

7.2 静态类与静态方法

静态类只能包含静态成员,不能实例化。静态方法可以直接通过类名调用,无需创建对象。

csharp

// 静态类
public static class MathHelper
{
    // 静态字段
    public static readonly double PI = 3.14159;

    // 静态方法
    public static double CalculateCircleArea(double radius)
    {
        return PI * radius * radius;
    }
}

// 使用静态类和静态方法
double area = MathHelper.CalculateCircleArea(5); // 直接通过类名调用

7.3 抽象类与抽象方法

抽象类不能被实例化,只能作为基类被继承。抽象方法没有实现体,必须在派生类中被重写。

csharp

// 抽象类
public abstract class Shape
{
    // 抽象方法
    public abstract double Area();

    // 普通方法
    public void Display()
    {
        Console.WriteLine($"Area: {Area()}");
    }
}

// 具体实现类
public class Circle : Shape
{
    public double Radius { get; set; }

    public override double Area()
    {
        return Math.PI * Radius * Radius;
    }
}

// 使用抽象类
Shape circle = new Circle { Radius = 5 };
circle.Display(); // 输出:Area: 78.5398163397448

7.4 密封类与密封方法

密封类使用 sealed 关键字声明,不能被继承。密封方法用于重写基类的虚方法,并禁止派生类进一步重写该方法。

csharp

// 基类
public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine("Animal speaks.");
    }
}

// 派生类,密封方法
public class Dog : Animal
{
    public sealed override void Speak()
    {
        Console.WriteLine("Dog barks.");
    }
}

// 错误:不能从密封类继承
// public class GoldenRetriever : Dog { }

7.5 虚方法与方法重写

虚方法使用 virtual 关键字声明,允许在派生类中重写。方法重写使用 override 关键字,提供方法的新实现。

csharp

// 基类
public class Shape
{
    public virtual double Area()
    {
        return 0;
    }
}

// 派生类
public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }

    public override double Area()
    {
        return Width * Height;
    }
}

// 使用虚方法和重写
Shape shape = new Rectangle { Width = 5, Height = 10 };
Console.WriteLine(shape.Area()); // 输出:50

7.6 方法重载

方法重载是指在同一个类中定义多个同名但参数不同的方法。

csharp

public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public double Add(double a, double b)
    {
        return a + b;
    }

    public int Add(int a, int b, int c)
    {
        return a + b + c;
    }
}

// 使用方法重载
Calculator calc = new Calculator();
int sum1 = calc.Add(1, 2); // 调用第一个 Add 方法
double sum2 = calc.Add(1.5, 2.5); // 调用第二个 Add 方法
int sum3 = calc.Add(1, 2, 3); // 调用第三个 Add 方法

7.7 方法参数传递(ref、out、in、params)

ref 参数

使用 ref 关键字传递参数,允许方法修改调用者提供的变量。参数必须在传递前初始化。

csharp

public void Swap(ref int a, ref int b)
{
    int temp = a;
    a = b;
    b = temp;
}

// 使用 ref 参数
int x = 10, y = 20;
Swap(ref x, ref y); // x = 20, y = 10
out 参数

使用 out 关键字传递参数,要求方法必须在返回前为参数赋值。参数不需要在传递前初始化。

csharp

public void SplitName(string fullName, out string firstName, out string lastName)
{
    string[] parts = fullName.Split(' ');
    firstName = parts[0];
    lastName = parts.Length > 1 ? parts[1] : "";
}

// 使用 out 参数
string fullName = "John Doe";
string first, last;
SplitName(fullName, out first, out last); // first = "John", last = "Doe"
in 参数

使用 in 关键字传递参数,确保方法不会修改参数的值,是只读的。

csharp

public void PrintValue(in int value)
{
    // value = 100; // 错误:不能修改 in 参数
    Console.WriteLine(value);
}

// 使用 in 参数
int number = 50;
PrintValue(in number);
params 参数

使用 params 关键字允许方法接受可变数量的参数,必须是方法的最后一个参数。

csharp

public int Sum(params int[] numbers)
{
    int sum = 0;
    foreach (int number in numbers)
    {
        sum += number;
    }
    return sum;
}

// 使用 params 参数
int total = Sum(1, 2, 3, 4, 5); // total = 15

8. 结构与枚举

8.1 结构类型

结构(struct)是一种值类型,通常用于表示轻量级对象,如点、矩形、日期等。

csharp

// 定义结构
public struct Point
{
    public double X;
    public double Y;

    public Point(double x, double y)
    {
        X = x;
        Y = y;
    }

    public double DistanceToOrigin()
    {
        return Math.Sqrt(X * X + Y * Y);
    }
}

// 使用结构
Point p = new Point(3, 4);
double distance = p.DistanceToOrigin(); // 5

8.2 结构与类比较

特性结构(struct)类(class)
类型值类型引用类型
内存位置栈或嵌入在对象中
继承不能继承其他类型可以继承基类和实现接口
实例化无需使用 new 关键字必须使用 new 关键字
默认构造函数自动提供必须显式定义
析构函数不允许允许

8.3 ref struct

ref struct 是一种特殊的结构,用于高性能场景,直接在栈上分配内存,不能在堆上分配。

csharp

// ref struct
public ref struct Span<T>
{
    private readonly T[] _array;
    private readonly int _start;
    private readonly int _length;

    public Span(T[] array, int start, int length)
    {
        _array = array;
        _start = start;
        _length = length;
    }

    public T this[int index]
    {
        get => _array[_start + index];
        set => _array[_start + index] = value;
    }
}

8.4 枚举类型

枚举(enum)是一种值类型,用于定义一组命名的常量。

csharp

// 定义枚举
public enum DayOfWeek
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
}

// 使用枚举
DayOfWeek today = DayOfWeek.Monday;
Console.WriteLine(today); // 输出:Monday

// 枚举与整数的转换
int dayValue = (int)today; // dayValue = 0
DayOfWeek day = (DayOfWeek)2; // day = Wednesday

8.5 标记枚举

标记枚举使用 [Flags] 属性,允许将枚举值组合使用。

csharp

[Flags]
public enum Permissions
{
    None = 0,
    Read = 1,
    Write = 2,
    Execute = 4,
    All = Read | Write | Execute
}

// 使用标记枚举
Permissions userPermissions = Permissions.Read | Permissions.Write;
if ((userPermissions & Permissions.Write) == Permissions.Write)
{
    Console.WriteLine("用户有写入权限");
}

8.6 枚举类型转换

枚举与其他类型之间的转换:

csharp

// 枚举转字符串
string dayName = DayOfWeek.Monday.ToString(); // "Monday"

// 字符串转枚举
DayOfWeek day = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), "Monday");

// 检查字符串是否是有效的枚举值
bool isValid = Enum.TryParse("Monday", out DayOfWeek result); // true

// 枚举与整数的转换
int value = (int)DayOfWeek.Tuesday; // 1
DayOfWeek day = (DayOfWeek)3; // Thursday

9. 高级编程特性

9.1 泛型

泛型允许创建参数化的类型和方法,提供类型安全而不损失性能。

csharp

// 泛型类
public class MyList<T>
{
    private T[] items = new T[10];
    private int count = 0;

    public void Add(T item)
    {
        if (count < items.Length)
            items[count++] = item;
    }

    public T Get(int index)
    {
        if (index < count)
            return items[index];
        throw new IndexOutOfRangeException();
    }
}

// 使用泛型类
MyList<int> intList = new MyList<int>();
intList.Add(10);
int value = intList.Get(0);

MyList<string> stringList = new MyList<string>();
stringList.Add("Hello");
string text = stringList.Get(0);

9.2 逆变与协变

逆变和协变是泛型类型参数的两种变体,允许安全地进行类型转换。

协变(out)

协变允许使用比泛型参数指定的类型更派生的类型。

csharp

// 协变接口
public interface IReadOnlyCollection<out T>
{
    int Count { get; }
    T Get(int index);
}

// 使用协变
IReadOnlyCollection<object> objects = new List<string>(); // 合法,因为 string 是 object 的子类
逆变(in)

逆变允许使用比泛型参数指定的类型更基类的类型。

csharp

// 逆变接口
public interface IComparer<in T>
{
    int Compare(T x, T y);
}

// 使用逆变
IComparer<object> objectComparer = new MyStringComparer(); // 合法,MyStringComparer 实现了 IComparer<string>

9.3 委托与事件

委托

委托是一种类型,它可以引用一个或多个方法。

csharp

// 定义委托
public delegate int MathOperation(int a, int b);

// 方法
public int Add(int a, int b) { return a + b; }
public int Subtract(int a, int b) { return a - b; }

// 使用委托
MathOperation operation = Add;
int result = operation(10, 5); // 调用 Add 方法

operation = Subtract;
result = operation(10, 5); // 调用 Subtract 方法
事件

事件是基于委托的一种机制,允许对象发布和订阅事件。

csharp

// 定义事件发布者
public class Button
{
    // 定义事件
    public event EventHandler Click;

    // 触发事件的方法
    public void OnClick()
    {
        Click?.Invoke(this, EventArgs.Empty);
    }
}

// 定义事件订阅者
public class Form
{
    private Button button = new Button();

    public Form()
    {
        // 订阅事件
        button.Click += Button_Click;
    }

    private void Button_Click(object sender, EventArgs e)
    {
        Console.WriteLine("按钮被点击了");
    }
}

9.4 多线程编程

多线程允许程序同时执行多个任务,提高程序的响应性和性能。

csharp

using System.Threading;

public class Program
{
    public static void Main()
    {
        // 创建线程
        Thread thread = new Thread(DoWork);
        thread.Start(); // 启动线程

        // 主线程继续执行
        Console.WriteLine("主线程继续执行...");

        // 等待线程完成
        thread.Join();
    }

    public static void DoWork()
    {
        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine($"工作线程: {i}");
            Thread.Sleep(100);
        }
    }
}

9.5 线程池

线程池管理一组工作线程,避免频繁创建和销毁线程的开销。

csharp

using System.Threading;

public class Program
{
    public static void Main()
    {
        // 将工作项排队到线程池
        ThreadPool.QueueUserWorkItem(DoWork);

        Console.WriteLine("主线程继续执行...");
        Thread.Sleep(2000); // 等待工作项完成
    }

    public static void DoWork(object state)
    {
        Console.WriteLine("线程池线程开始工作");
        Thread.Sleep(1000);
        Console.WriteLine("线程池线程完成工作");
    }
}

9.6 Task 并行编程

Task 是 .NET 4.0 引入的高级并行编程模型,基于线程池。

csharp

using System.Threading.Tasks;

public class Program
{
    public static async Task Main()
    {
        // 创建并启动任务
        Task<int> task = Task.Run(() =>
        {
            Thread.Sleep(1000);
            return 42;
        });

        // 等待任务完成并获取结果
        int result = await task;
        Console.WriteLine($"任务结果: {result}");
    }
}

9.7 async/await 异步编程

async 和 await 是 C# 提供的语法糖,用于简化异步编程。

csharp

using System.Threading.Tasks;

public class Program
{
    public static async Task Main()
    {
        Console.WriteLine("开始异步操作");
        
        // 异步调用
        string result = await DownloadDataAsync();
        
        Console.WriteLine($"操作完成: {result}");
    }

    public static async Task<string> DownloadDataAsync()
    {
        // 模拟异步下载
        await Task.Delay(2000);
        return "下载完成";
    }
}

9.8 任务并行库

任务并行库(TPL)提供了高级的并行编程功能,如并行循环和并行 LINQ。

csharp

using System.Threading.Tasks;

public class Program
{
    public static void Main()
    {
        // 并行 for 循环
        Parallel.For(0, 10, i =>
        {
            Console.WriteLine($"线程 {Task.CurrentId} 处理: {i}");
            Thread.Sleep(100);
        });

        // 并行 foreach
        string[] files = System.IO.Directory.GetFiles(@"C:\Temp");
        Parallel.ForEach(files, file =>
        {
            Console.WriteLine($"处理文件: {file}");
        });
    }
}

10. 常用 API 与技术

10.1 字符串处理(string、StringBuilder)

string 类

csharp

string s1 = "Hello";
string s2 = "World";
string s3 = s1 + " " + s2; // "Hello World"

// 字符串操作
bool contains = s3.Contains("World"); // true
string upper = s3.ToUpper(); // "HELLO WORLD"
string[] parts = s3.Split(' '); // ["Hello", "World"]
string substring = s3.Substring(6); // "World"
StringBuilder 类

用于高效地构建字符串,避免频繁创建新的字符串对象。

csharp

StringBuilder sb = new StringBuilder();
sb.Append("Hello");
sb.Append(" ");
sb.Append("World");
string result = sb.ToString(); // "Hello World"

10.2 格式化与类型转换

字符串格式化

csharp

string name = "John";
int age = 30;
string message = string.Format("My name is {0} and I'm {1} years old.", name, age);

// 插值字符串(C# 6.0+)
string message2 = $"My name is {name} and I'm {age} years old.";

// 数字格式化
double number = 1234.5678;
string formatted = number.ToString("N2"); // "1,234.57"
类型转换

csharp

// 字符串转整数
int num = int.Parse("123");
bool success = int.TryParse("123", out int result);

// 其他类型转换
double d = 3.14;
int i = Convert.ToInt32(d); // 3
string s = Convert.ToString(42); // "42"

10.3 日期与时间处理

csharp

// 获取当前日期和时间
DateTime now = DateTime.Now;
DateTime today = DateTime.Today;

// 创建特定日期
DateTime birthday = new DateTime(1990, 5, 15);

// 日期计算
DateTime tomorrow = now.AddDays(1);
DateTime nextMonth = now.AddMonths(1);
TimeSpan duration = tomorrow - now; // 1 天

// 日期格式化
string formattedDate = now.ToString("yyyy-MM-dd");
string formattedTime = now.ToString("HH:mm:ss");
string formatted = now.ToString("f"); // "2023年5月1日 14:30"

// 时区转换
DateTime utcTime = DateTime.UtcNow;
DateTime localTime = utcTime.ToLocalTime();

10.4 数学运算

csharp

// 基本数学运算
int a = 10, b = 3;
int sum = a + b;
int difference = a - b;
int product = a * b;
double quotient = (double)a / b; // 3.3333...

// Math 类
double x = 3.14;
double abs = Math.Abs(-5); // 5
double ceiling = Math.Ceiling(x); // 4
double floor = Math.Floor(x); // 3
double round = Math.Round(x); // 3
double max = Math.Max(10, 20); // 20
double min = Math.Min(10, 20); // 10
double pow = Math.Pow(2, 3); // 8
double sqrt = Math.Sqrt(16); // 4

10.5 文件与流操作

文件操作

csharp

using System.IO;

// 写入文件
string content = "Hello, File!";
File.WriteAllText("test.txt", content);

// 读取文件
string readContent = File.ReadAllText("test.txt");

// 检查文件是否存在
bool exists = File.Exists("test.txt");

// 删除文件
if (exists)
    File.Delete("test.txt");
流操作

csharp

using System.IO;

// 使用 StreamWriter 写入文件
using (StreamWriter writer = new StreamWriter("test.txt"))
{
    writer.WriteLine("Line 1");
    writer.WriteLine("Line 2");
}

// 使用 StreamReader 读取文件
using (StreamReader reader = new StreamReader("test.txt"))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        Console.WriteLine(line);
    }
}

10.6 集合类(Array、ArrayList、List 等)

ArrayList

动态数组,可存储不同类型的对象,但不是类型安全的。

csharp

ArrayList list = new ArrayList();
list.Add(10);
list.Add("Hello");
list.Add(new Person());

int first = (int)list[0]; // 需要强制类型转换
List<T>

泛型集合,类型安全,性能更好。

csharp

List<int> numbers = new List<int>();
numbers.Add(10);
numbers.Add(20);
int first = numbers[0]; // 无需类型转换

// 遍历列表
foreach (int number in numbers)
{
    Console.WriteLine(number);
}

// 列表操作
bool contains = numbers.Contains(10); // true
numbers.Remove(20);
int count = numbers.Count; // 1
Dictionary<TKey, TValue>

键值对集合,基于哈希表。

csharp

Dictionary<string, int> ages = new Dictionary<string, int>();
ages.Add("John", 30);
ages.Add("Alice", 25);

int johnAge = ages["John"]; // 30

// 检查键是否存在
if (ages.ContainsKey("Alice"))
{
    int aliceAge = ages["Alice"];
}

// 遍历字典
foreach (KeyValuePair<string, int> pair in ages)
{
    Console.WriteLine($"{pair.Key}: {pair.Value}");
}

10.7 线程与任务

见 9.4-9.7 节内容。

10.8 GUID 与加密

GUID

全局唯一标识符,用于生成唯一标识。

csharp

Guid guid = Guid.NewGuid();
string guidString = guid.ToString(); // 例如:"3f2504e0-4f89-11d3-9a0c-0305e82c3301"
MD5 加密

csharp

using System.Security.Cryptography;
using System.Text;

string input = "Hello, World!";
using (MD5 md5 = MD5.Create())
{
    byte[] inputBytes = Encoding.UTF8.GetBytes(input);
    byte[] hashBytes = md5.ComputeHash(inputBytes);
    
    // 转换为十六进制字符串
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < hashBytes.Length; i++)
    {
        sb.Append(hashBytes[i].ToString("x2"));
    }
    string hash = sb.ToString(); // MD5 哈希值
}

10.9 序列化与反序列化

JSON 序列化

csharp

using System.Text.Json;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// 序列化
Person person = new Person { Name = "John", Age = 30 };
string json = JsonSerializer.Serialize(person); // {"Name":"John","Age":30}

// 反序列化
Person deserialized = JsonSerializer.Deserialize<Person>(json);

10.10 特性(Attribute)

特性允许向程序元素(类、方法、属性等)添加元数据。

csharp

// 定义自定义特性
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorAttribute : Attribute
{
    public string Name { get; }
    public string Version { get; }

    public AuthorAttribute(string name, string version = "1.0")
    {
        Name = name;
        Version = version;
    }
}

// 使用特性
[Author("John Doe", "2.0")]
public class MyClass
{
    [Author("Jane Smith")]
    public void MyMethod()
    {
        // 方法实现
    }
}

10.11 反射(Reflection)

反射允许在运行时检查和操作类型、方法、属性等。

csharp

// 获取类型信息
Type type = typeof(MyClass);
Console.WriteLine($"类型名称: {type.Name}");

// 获取特性信息
AuthorAttribute author = type.GetCustomAttribute<AuthorAttribute>();
if (author != null)
{
    Console.WriteLine($"作者: {author.Name}, 版本: {author.Version}");
}

// 创建实例
object instance = Activator.CreateInstance(type);

// 调用方法
MethodInfo method = type.GetMethod("MyMethod");
method.Invoke(instance, null);

10.12 INI 文件读写

csharp

using System.IO;

public class IniFile
{
    private Dictionary<string, Dictionary<string, string>> sections = new Dictionary<string, Dictionary<string, string>>();
    private string filePath;

    public IniFile(string filePath)
    {
        this.filePath = filePath;
        Read();
    }

    private void Read()
    {
        if (!File.Exists(filePath))
            return;

        string currentSection = null;
        foreach (string line in File.ReadAllLines(filePath))
        {
            string trimmed = line.Trim();
            if (trimmed.StartsWith("[") && trimmed.EndsWith("]"))
            {
                currentSection = trimmed.Substring(1, trimmed.Length - 2);
                sections[currentSection] = new Dictionary<string, string>();
            }
            else if (!string.IsNullOrEmpty(currentSection) && trimmed.Contains("="))
            {
                int index = trimmed.IndexOf("=");
                string key = trimmed.Substring(0, index).Trim();
                string value = trimmed.Substring(index + 1).Trim();
                sections[currentSection][key] = value;
            }
        }
    }

    public string GetValue(string section, string key, string defaultValue = "")
    {
        if (sections.TryGetValue(section, out Dictionary<string, string> sectionData) &&
            sectionData.TryGetValue(key, out string value))
        {
            return value;
        }
        return defaultValue;
    }

    public void SetValue(string section, string key, string value)
    {
        if (!sections.TryGetValue(section, out Dictionary<string, string> sectionData))
        {
            sectionData = new Dictionary<string, string>();
            sections[section] = sectionData;
        }
        sectionData[key] = value;
        Save();
    }

    private void Save()
    {
        using (StreamWriter writer = new StreamWriter(filePath))
        {
            foreach (var section in sections)
            {
                writer.WriteLine($"[{section.Key}]");
                foreach (var keyValue in section.Value)
                {
                    writer.WriteLine($"{keyValue.Key}={keyValue.Value}");
                }
                writer.WriteLine();
            }
        }
    }
}

阶段项目:银行客户管理系统

项目需求分析

  1. 系统概述

    • 设计一个银行客户管理系统,用于管理客户信息和账户交易。
    • 系统需要支持客户信息的增删改查,账户管理和交易记录。
  2. 功能需求

    • 客户管理:添加、修改、删除和查询客户信息
    • 账户管理:为客户创建账户、查询账户余额
    • 交易处理:存款、取款、转账
    • 报表生成:客户列表、账户余额报表
  3. 非功能需求

    • 数据安全性:客户信息和交易数据需要安全存储
    • 性能要求:系统响应时间在可接受范围内
    • 易用性:界面友好,操作简单

系统架构设计

  1. 三层架构

    • 表示层(UI):负责与用户交互的界面
    • 业务逻辑层(BLL):处理业务逻辑和规则
    • 数据访问层(DAL):负责数据的存储和检索
  2. 技术选型

    • 开发语言:C#
    • 数据库:SQL Server 或 MySQL
    • 开发工具:Visual Studio
  3. 模块划分

    • 客户管理模块
    • 账户管理模块
    • 交易处理模块
    • 报表生成模块

数据库设计

  1. 实体设计

    • 客户(Customer):客户 ID、姓名、地址、电话、电子邮件
    • 账户(Account):账户 ID、客户 ID、账户类型、余额、开户日期
    • 交易(Transaction):交易 ID、账户 ID、交易类型、金额、交易日期
  2. 表结构示例

sql

CREATE TABLE Customers (
    CustomerID INT PRIMARY KEY IDENTITY,
    Name VARCHAR(100) NOT NULL,
    Address VARCHAR(200),
    Phone VARCHAR(20),
    Email VARCHAR(100)
);

CREATE TABLE Accounts (
    AccountID INT PRIMARY KEY IDENTITY,
    CustomerID INT FOREIGN KEY REFERENCES Customers(CustomerID),
    AccountType VARCHAR(50) NOT NULL,
    Balance DECIMAL(18, 2) NOT NULL DEFAULT 0,
    OpenDate DATETIME NOT NULL DEFAULT GETDATE()
);

CREATE TABLE Transactions (
    TransactionID INT PRIMARY KEY IDENTITY,
    AccountID INT FOREIGN KEY REFERENCES Accounts(AccountID),
    TransactionType VARCHAR(50) NOT NULL,
    Amount DECIMAL(18, 2) NOT NULL,
    TransactionDate DATETIME NOT NULL DEFAULT GETDATE()
);

功能模块实现

  1. 客户管理模块

    • 添加客户:收集客户信息并保存到数据库
    • 修改客户:根据客户 ID 更新客户信息
    • 删除客户:根据客户 ID 删除客户及其关联账户
    • 查询客户:根据条件查询客户信息
  2. 账户管理模块

    • 创建账户:为指定客户创建新账户
    • 查询账户:根据账户 ID 或客户 ID 查询账户信息
    • 账户列表:列出所有账户或指定客户的账户
  3. 交易处理模块

    • 存款:增加账户余额并记录交易
    • 取款:减少账户余额并记录交易,检查余额是否充足
    • 转账:从一个账户扣款并转入另一个账户,记录两笔交易
  4. 报表生成模块

    • 客户列表:生成所有客户的报表
    • 账户余额报表:生成所有账户或指定客户的账户余额报表
    • 交易历史:生成指定账户的交易历史记录

系统测试与优化

  1. 单元测试

    • 测试各个模块的功能是否正常工作
    • 测试边界条件和异常情况的处理
  2. 集成测试

    • 测试各个模块之间的交互是否正常
    • 测试数据在不同模块之间的流转是否正确
  3. 性能测试

    • 测试系统在高并发情况下的性能表现
    • 找出性能瓶颈并进行优化
  4. 安全测试

    • 测试系统的安全性,包括数据加密、访问控制等
    • 检查是否存在安全漏洞
  5. 用户反馈与优化

    • 收集用户反馈,对系统进行改进和优化
    • 修复发现的问题,提高系统的稳定性和易用性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值