目录
[一、Hashtable 哈希表](#一、Hashtable 哈希表)
[1. 简介](#1. 简介)
[2. 常用方法 & 完整代码](#2. 常用方法 & 完整代码)
[二、SortedList 有序键值列表](#二、SortedList 有序键值列表)
[1. 简介](#1. 简介)
[2. 常用方法 & 完整代码](#2. 常用方法 & 完整代码)
[1. 栈 Stack](#1. 栈 Stack)
[2. 队列 Queue](#2. 队列 Queue)
[3. 完整演示代码](#3. 完整演示代码)
[1. 核心概念](#1. 核心概念)
[2. 成员分类](#2. 成员分类)
[3. 示例代码](#3. 示例代码)
[1. 区别总结](#1. 区别总结)
[2. 三种属性写法 + 只读属性](#2. 三种属性写法 + 只读属性)
[3. 属性拦截实战案例](#3. 属性拦截实战案例)
[1. 作用](#1. 作用)
[2. 重载构造函数](#2. 重载构造函数)
[1. 作用](#1. 作用)
[2. 示例代码](#2. 示例代码)
[1. 集合部分](#1. 集合部分)
[2. 面向对象核心](#2. 面向对象核心)
一、Hashtable 哈希表
1. 简介
命名空间:using System.Collections; Hashtable 是 .NET 早期非泛型键值对集合,基于哈希算法实现数据快速寻址查找。
- 底层原理:通过哈希函数将
Key转为哈希码,直接定位数据存储位置,查询效率极高; - 缺陷:存储
object类型,类型不安全,频繁发生装箱、拆箱; - 现状:新项目基本被泛型
Dictionary替代,仅作历史知识了解。
2. 常用方法 & 完整代码
cs
using System;
using System.Collections;
namespace _2hashTable_哈希表
{
internal class Program
{
static void Main(string[] args)
{
Hashtable table = new Hashtable()
{
{ 1, "这是1" },
{ true, "这是true1" }
};
// 1. Add:添加键值对
table.Add(0, "这是0");
table.Add(2, new int[] { 1, 2, 3 });
// 2. Count:获取键值对总数
Console.WriteLine(table.Count);
// 3. 通过键取值
Console.WriteLine(table[1]);
// 4. 修改键对应的值
table[1] = 100;
Console.WriteLine(table[1]);
// 5. 获取所有键、所有值集合
Console.WriteLine(table.Keys);
Console.WriteLine(table.Values);
// 6. Remove:根据键移除键值对
table.Remove(0);
// 7. ContainsKey:判断是否包含指定键
Console.WriteLine(table.ContainsKey(0));
// 8. 遍历所有值
foreach (var item in table.Values)
{
Console.WriteLine(item + "---");
}
}
}
}
二、SortedList 有序键值列表
1. 简介
命名空间:using System.Collections; SortedList 同样是非泛型键值对集合 ,核心特点:自动根据 Key 升序排序。
- 支持通过键 、索引两种方式操作元素;
- Key 必须具备可比较性,不同数据类型的 Key 不能混用;
- 属于早期集合,现代开发优先使用泛型版本。
2. 常用方法 & 完整代码
cs
using System;
using System.Collections;
namespace _3sortList_有序列表
{
internal class Program
{
static void Main(string[] args)
{
SortedList list = new SortedList()
{
{ 13, "秦琼" },
{ 10, "罗成" },
{ 3, "裴元庆" },
{ 2, "宇文成都" },
{ 1, "李元霸" }
};
// 1. 添加键值对
list.Add(4, "熊阔海");
// 2. 根据键修改值
list[10] = "杨林";
// 3. 删除元素:按键删除 / 按索引删除
list.Remove(4);
list.RemoveAt(3);
// 4. 获取全部键、全部值
Console.WriteLine(list.Keys);
Console.WriteLine(list.Values);
// 5. 通过索引取值、取键
Console.WriteLine(list.GetByIndex(0));
Console.WriteLine(list.GetKey(0));
// 6. 遍历值集合
for (int i = 0; i < list.GetValueList().Count; i++)
{
Console.WriteLine(list.GetValueList()[i] + "------------");
}
foreach (var item in list.Values)
{
Console.WriteLine(item + "++++");
}
}
}
}
三、栈(Stack)和队列(Queue)
二者是两种经典线性容器,依靠固定存取规则工作,广泛应用于算法、消息队列、方法调用栈等场景。
1. 栈 Stack
规则:先入后出(后进先出 LIFO)
Push():入栈,向栈顶添加元素;Pop():出栈,删除并返回栈顶元素;Peek():查看栈顶元素,不删除;- 分为非泛型 Stack 和泛型 Stack<T>,推荐使用泛型版本。
2. 队列 Queue
规则:先入先出(先进先出 FIFO)
Enqueue():入队,向队尾添加元素;Dequeue():出队,删除并返回队首元素;Peek():查看队首元素,不删除;
3. 完整演示代码
cs
using System;
using System.Collections;
using System.Collections.Generic;
namespace _4栈和队列
{
internal class Program
{
static void Main(string[] args)
{
#region 栈 Stack
Stack stack1 = new Stack();
stack1.Push("张三");
stack1.Push("李四");
stack1.Push("王五");
Console.WriteLine(stack1.Pop()); // 出栈:王五
Console.WriteLine(stack1.Peek()); // 查看栈顶:李四
// 遍历栈
foreach (var i in stack1)
{
Console.WriteLine(i + "-----");
}
#endregion
#region 队列 Queue
Queue<string> queue = new Queue<string>();
queue.Enqueue("hello1");
queue.Enqueue("hello2");
queue.Enqueue("hello3");
Console.WriteLine(queue.Dequeue()); // 出队:hello1
Console.WriteLine(queue.Peek()); // 查看队首:hello2
foreach (var item in queue)
{
Console.WriteLine(item);
}
#endregion
}
}
}
四、面向对象基础:类和对象
1. 核心概念
- 类:模板、抽象描述,定义属性和行为;
- 对象:根据类实例化出来的具体实体;
- 创建对象依靠构造函数,通过对象调用类的成员。
2. 成员分类
- 字段:类内部的成员变量;
- 方法:类的行为,分为静态方法 (类名调用)、非静态方法(对象调用)。
3. 示例代码
cs
using System;
namespace _5类和对象的创建
{
internal class Program
{
static void Main(string[] args)
{
// 实例化对象
People zs = new People();
zs.id = "002";
People ls = new People();
ls.id = "001";
// 调用非静态方法(对象调用)
zs.F1();
ls.F1();
// 调用静态方法(类名直接调用)
People.F2(10);
}
}
public class People
{
// 字段(成员变量)
string name;
int age;
bool sex;
public string id;
private int _height;
// 非静态方法
public void F1()
{
Console.WriteLine("非静态无返回值方法");
}
// 静态方法
public static int F2(int a)
{
return 100000;
}
}
}
五、访问修饰符
用于控制类、字段、方法、属性的访问权限,常用四种:
public:公共,任何位置都可访问;private:私有,仅当前类内部可访问(默认权限);internal:内部,当前项目内可访问,跨项目不可访问;protected:受保护,当前类和派生类可访问。
跨项目访问说明
若要在其他项目访问本项目的类:
- 目标项目添加项目引用;
- 引入对应命名空间;
- 被访问的类 / 成员必须标记为
public
cs
using System;
using _5类和对象的创建;
namespace _6访问修饰符的测试
{
internal class Program
{
static void Main(string[] args)
{
Class1 c1 = new Class1();
c1.age = 1;
// 引用其他项目的 public 类
People p = new People();
p.id = "002";
}
}
internal class Class1
{
public int age;
}
}
六、字段与属性
1. 区别总结
- 字段 :类内部存储数据的变量,一般设为
private,仅供内部使用; - 属性 :对外公开的访问接口,包含
get(取值)、set(赋值)访问器; - 核心作用:属性拦截,在赋值 / 取值时做数据校验、逻辑处理;
- 语法演变:完整写法 → 简写 → 自动属性(语法糖)。
2. 三种属性写法 + 只读属性
cs
using System;
namespace _7属性和字段
{
internal class Program
{
static void Main(string[] args)
{
People p = new People();
p.Name = "T"; // 触发 set 访问器
Console.WriteLine(p.Name); // 触发 get 访问器
People p3 = new People();
p3.Name = "Y";
Console.WriteLine(p3.Name + ":" + p3.Id);
}
}
public class People
{
// 私有字段
private string _name;
// 1. 完整属性写法
public string Name
{
get
{
Console.WriteLine("get访问器触发了");
return _name;
}
set
{
Console.WriteLine("set访问器触发了" + value);
if (value.Length == 0)
{
throw new Exception("不能赋空字符串");
}
_name = value;
}
}
// 2. Lambda 简写属性
private int _a1;
public int A1 { get => _a1; set => _a1 = value; }
// 3. 自动属性(语法糖),可设置默认值
public string Id { get; set; } = "001";
// 4. 只读属性:只有 get,无法赋值
public string Msg { get; }
}
}
3. 属性拦截实战案例
利用 get/set 做数据合法性校验,是属性最常用场景:
cs
using System;
using System.Linq;
namespace _8属性拦截例子
{
internal class Dog
{
public int a = 100;
private int _age;
// 年龄范围校验
public int Age
{
get
{
_age *= 10;
return _age;
}
set
{
if (value < 0 || value > 20)
{
throw new Exception("年龄不在合适的范围内");
}
_age = value;
}
}
private char[] colors = { '黄', '白', '黑' };
private char _color;
// 颜色范围校验
public char Color
{
get { return _color; }
set
{
if (!colors.Contains(value))
{
throw new Exception("颜色不合适");
}
_color = value;
}
}
}
internal class Program
{
static void Main(string[] args)
{
Dog d1 = new Dog();
d1.Age = 19;
Console.WriteLine(d1.Age);
d1.Color = '白';
Console.WriteLine(d1.Color);
}
}
}
七、构造函数
1. 作用
- 和类名完全一致,无返回值;
- 创建对象时自动执行,用于初始化成员数据;
- 类默认自带一个无参构造函数,自定义有参构造后,默认无参构造会失效。
2. 重载构造函数
一个类可以定义多个参数不同的构造函数,实现对象多种初始化方式:
cs
using System;
namespace _9构造函数
{
internal class Program
{
static void Main(string[] args)
{
People p1 = new People();
Console.WriteLine(p1.Name);
People p3 = new People("李四", 20);
Console.WriteLine(p3.Name);
}
}
public class People
{
public string Name { get; set; }
public int Age { get; set; }
// 无参构造函数
public People()
{
Name = "张三";
this.Age = 10;
}
// 有参构造函数(重载)
public People(string n, int a)
{
this.Name = n;
this.Age = a;
Console.WriteLine(this.Name + "---------");
}
}
}
this:代表当前实例对象,用来区分局部参数和类成员。
八、析构函数
1. 作用
- 语法:
~类名(){},无参数、无修饰符; - 对象被 GC 垃圾回收 时自动执行,用于释放非托管资源;
- 手动调用
GC.Collect()可强制触发垃圾回收,测试析构函数。
2. 示例代码
cs
using System;
namespace _10析构函数
{
internal class Program
{
static void Main(string[] args)
{
People p = new People();
p = null; // 切断引用,对象等待回收
GC.Collect(); // 强制垃圾回收
Console.ReadKey();
}
}
public class People
{
// 析构函数
~People()
{
Console.WriteLine("对象被GC回收了");
}
}
}
九、总结
1. 集合部分
Hashtable/SortedList:早期非泛型键值集合,类型不安全,新项目不推荐使用;Stack栈:先入后出;Queue队列:先入先出,是经典数据结构;
2. 面向对象核心
- 类与对象:类是模板,对象是实例;静态成员靠类调用,实例成员靠对象调用;
- 访问修饰符 :控制访问范围,
public跨项目可用,internal仅限当前项目; - 字段 & 属性:字段存数据(私有),属性对外提供访问 + 数据拦截校验;
- 构造函数:创建对象、初始化数据,支持重载;
- 析构函数:对象销毁时执行,由 GC 垃圾回收触发