c#基础知识合集13 哈希表、有序列表、栈和队列、类和对象的创建、属性和字段、字段和属性的区别、属性拦截、构造函数、析构函数
·
哈希表(Hashtable 与 Dictionary<TKey, TValue>)
- 原理:哈希表通过哈希函数将键映射到一个哈希码,进而确定值的存储位置,实现快速查找。
Hashtable是早期的哈希表实现,Dictionary<TKey, TValue>是泛型版本。 - 特点:
- 快速查找:平均情况下,查找、插入和删除操作的时间复杂度接近 \(O(1)\)。
- 键唯一性:键必须唯一,否则会覆盖已有的键值对。
- 示例(
Dictionary<TKey, TValue>):
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("one", 1);
int value;
bool success = dict.TryGetValue("one", out value);
有序列表(SortedList<TKey, TValue> 与 SortedDictionary<TKey, TValue>)
- 原理:有序列表会根据键的顺序对元素进行排序存储。
SortedList<TKey, TValue>内部使用数组和二分查找,SortedDictionary<TKey, TValue>使用红黑树。 - 特点:
- 按键排序:元素按键的顺序排列。
- 查找效率:
SortedDictionary<TKey, TValue>的插入和删除操作平均时间复杂度为 \(O(\log n)\),SortedList<TKey, TValue>在插入和删除大量元素时性能稍逊,因为可能需要重新分配数组空间,但查找性能也为 \(O(\log n)\)。
- 示例(
SortedDictionary<TKey, TValue>):
SortedDictionary<int, string> sortedDict = new SortedDictionary<int, string>();
sortedDict.Add(3, "three");
sortedDict.Add(1, "one");
foreach (var pair in sortedDict)
{
Console.WriteLine($"{pair.Key}: {pair.Value}");
}
-
栈和队列
栈(Stack<T>):
原理:遵循后进先出(LIFO, Last In First Out)原则。元素从栈顶压入和弹出。
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
int top = stack.Pop(); // 返回2
队列(Queue<T>):
原理:遵循先进先出(FIFO, First In First Out)原则。元素从队尾入队,从队头出队。
Queue<int> queue = new Queue<int>();
queue.Enqueue(1);
queue.Enqueue(2);
int first = queue.Dequeue(); // 返回1
类和对象的创建
类的定义:类是一种用户自定义的数据类型,封装了数据(字段和属性)和行为(方法)。
- 对象的创建:使用
new关键字创建类的实例(对象)。
class Person
{
// 字段
private string name;
// 属性
public string Name
{
get { return name; }
set { name = value; }
}
// 构造函数
public Person(string initialName)
{
name = initialName;
}
}
class Program
{
static void Main()
{
Person person = new Person("Alice");
Console.WriteLine(person.Name);
}
}
属性和字段
- 字段:是类中用于存储数据的变量,直接表示数据状态。通常声明为
private以实现封装。 - 属性:是一种特殊的成员,提供对字段的访问控制。属性有
get和set访问器,可以包含逻辑。
class Circle
{
// 字段
private double radius;
// 属性
public double Radius
{
get { return radius; }
set
{
if (value > 0)
{
radius = value;
}
}
}
}
字段和属性的区别
- 封装性:字段通常设为
private,直接访问可能破坏数据完整性;属性通过get和set访问器控制访问,实现更好的封装。 - 数据验证:属性的
set访问器可进行数据验证,字段无法直接进行。 - 可观察性:属性可添加逻辑,如日志记录,字段无此功能。
属性拦截(System.ComponentModel.INotifyPropertyChanged)
- 用途:用于通知客户端(如 UI)属性值已更改。
using System.ComponentModel;
class ObservableObject : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set
{
if (_name!= value)
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
构造函数
- 用途:用于初始化对象的状态,在创建对象时自动调用。
class Rectangle
{
private int width;
private int height;
public Rectangle(int w, int h)
{
width = w;
height = h;
}
}
析构函数
- 用途:用于在对象被销毁时执行清理操作,如释放非托管资源。
class ResourceHolder
{
// 假设这里有非托管资源
~ResourceHolder()
{
// 清理非托管资源的代码
}
}
- 注意:在 C# 中,垃圾回收器会自动管理对象的生命周期,析构函数通常用于处理非托管资源。但尽量使用
IDisposable接口和using语句来进行资源清理,因为析构函数的调用时间不确定。
更多推荐

所有评论(0)