13.C# —— 哈希表、排序列表、访问修饰符与属性拦截、构造/析构函数

目录

[一、Hashtable 哈希表](#一、Hashtable 哈希表)

[1. 简介](#1. 简介)

[2. 常用方法 & 完整代码](#2. 常用方法 & 完整代码)

[二、SortedList 有序键值列表](#二、SortedList 有序键值列表)

[1. 简介](#1. 简介)

[2. 常用方法 & 完整代码](#2. 常用方法 & 完整代码)

三、栈(Stack)和队列(Queue)

[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;
        }
    }
}

五、访问修饰符

用于控制类、字段、方法、属性的访问权限,常用四种:

  1. public:公共,任何位置都可访问;
  2. private:私有,仅当前类内部可访问(默认权限);
  3. internal:内部,当前项目内可访问,跨项目不可访问;
  4. protected:受保护,当前类和派生类可访问。

跨项目访问说明

若要在其他项目访问本项目的类:

  1. 目标项目添加项目引用
  2. 引入对应命名空间;
  3. 被访问的类 / 成员必须标记为 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. 区别总结

  1. 字段 :类内部存储数据的变量,一般设为 private,仅供内部使用;
  2. 属性 :对外公开的访问接口,包含 get(取值)、set(赋值)访问器;
  3. 核心作用:属性拦截,在赋值 / 取值时做数据校验、逻辑处理;
  4. 语法演变:完整写法 → 简写 → 自动属性(语法糖)。

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. 集合部分

  1. Hashtable / SortedList:早期非泛型键值集合,类型不安全,新项目不推荐使用;
  2. Stack 栈:先入后出;Queue 队列:先入先出,是经典数据结构;

2. 面向对象核心

  1. 类与对象:类是模板,对象是实例;静态成员靠类调用,实例成员靠对象调用;
  2. 访问修饰符 :控制访问范围,public 跨项目可用,internal 仅限当前项目;
  3. 字段 & 属性:字段存数据(私有),属性对外提供访问 + 数据拦截校验;
  4. 构造函数:创建对象、初始化数据,支持重载;
  5. 析构函数:对象销毁时执行,由 GC 垃圾回收触发
相关推荐
JaydenAI12 小时前
[MAF预定义ChatClient中间件-05]动态修改对话配置的两种解决方案
ai·c#·agent·maf·chatclient管道
IronMurphy13 小时前
AI Agent 学习day4 从 RAG 检索到 Function Call:一文理解大模型问答系统的完整链路
人工智能·学习·c#
爱学习的程序媛13 小时前
C 语言全景指南:从底层原理到工业级实战
c++·c#·c
魔法阵维护师13 小时前
从零开发游戏需要学习的c#模块,第二十九章(经验值与升级系统)
学习·游戏·c#
JaydenAI13 小时前
[MAF预定义ChatClient中间件-04]ReducingChatClient——通过精减对话实施又不丢失基本语义
ai·c#·agent·maf·chatclient管道·对话历史压缩
小满Autumn13 小时前
WPF 进阶:样式、触发器与控件模板
c#·.net·wpf
光泽雨13 小时前
C# 扩展方法(Extension Method)在语法上的核心灵魂。
开发语言·c#
影寂ldy14 小时前
C#Lambda表达式
开发语言·c#
z落落14 小时前
C# 局部方法 + Lambda表达式 + 三大委托和三大委托的区别和手写 Array.Find 底层源码原理(自定义MyArray.Find)
开发语言·c#