無語勝言 发表于 2023-10-18 02:30:01

C#学习笔记--数据结构、泛型、委托事件等进阶知识点

C#进阶

简单数据结构类

ArrayList

元素类型以Object类型存储,支持增删查改的数组容器。
因而存在装箱拆箱操作,谨慎使用。
//ArrayList
ArrayList array=new ArrayList();
//增=================
array.Add("Hello");
array.Add(true);
array.Add("Tony");//添加单个元素
array.Add("Hello");
array.Add("World");

ArrayList array2=new ArrayList();
array2.Add("123");
array.AddRange(array2);//从数组添加元素

//插入
array.Insert(1,"456");

//删除==================
array.Remove("Hello");
array.RemoveAt(1);//根据索引移除元素
array.Clear();//清空
//查=================
array;
//查看元素是否存储在
if(array.Contains(true))
{
   
}
//正向查找某个元素
//返回索引未找到则返回-1
array.IndexOf("Hello");
//反向查找元素位置
array.LastIndexOf("Hello");
//改=======================
array="123";

//遍历======
//区别长度(已经使用的容量)和容量
//容量
array.Capacity;
for(int i=0;i<array.Count;i++)
{
    Console.WriteLine(array);
}
//迭代器遍历
foreach(object obj in array)
{
    Console.WriteLine(item);
}
//装箱拆箱Queue

本质:也是一个object数组
//栈 先进后出
//声明
Stack stack=new Stack();

//========增===压栈
stack.Push(1);
stack.Push("23");
stack.Push("Tony");
stack.Push(66.6);
//=======取====弹栈
object o=stack.Pop();
//======查
//栈只能查看栈顶的内容,无索引器不可根据索引查看
Object look=stack.Peek();
//查看元素中有无内容
if(stack.Contains("Tony"))
{
        Console.WriteLine("该元素存在!");   
}

//清空
stack.Clear();
//遍历
foreach(object item in stack)
{
    Console.WriteLine(item);
    //从栈顶取元素
}
//将栈转换为数组
object[] stackArray=stack.ToArray();
//栈顶元素在数组前部分
//循环弹栈
while(stack.Count>0)
{
    object obj=stack.Pop();
    Console.WriteLine(obj);
}
//存在装箱拆箱Hashtable

本质:存储也是以object存储。散列表 ,基于hash代码组织起来的键值对
可以做到访问效率是O(1)
//队列先进先出
//声明
Queue queue=new Queue();

//增
queue.Enqueue(1);
queue.Enqueue(3.15f);
queue.Enqueue("Tony");
//取
queue.Dequeue();
//查
queue.Peek();
if(queue.Contains(3.15f))
{
    //打印
}
//改 只能清空
queue.Clear();
//遍历
queue.Count();
foreach(object item in queue)
{
    Console.WriteLine(item);
}
//转成数组
object[] objs=queue.ToArray();
for(int i=0;i<objs.Length;i++)
{
    //打印
   Console.WriteLine(objs);
}
//循环出列
while(queue.Count>0)
{
    object obj=queue.Dequeue();
    Console.WriteLine(obj);
}泛型

泛型

泛型实现了类型参数化,达到代码重用目的,通过类型参数化来实现同一份代码操作多种类想,
泛型相当于类型占位符,定义类或者方法时使用替代符代表变量类型,
当真正使用类或方法时候再具体指定类型
泛型分类:泛型类,泛型方法,泛型接口
//HashTable
//声明
Hashtable hashtable=newHashtable();

//增加键不能重复
hashtable.Add(1,"123");
hashtable.Add("name","TonyChang");
hashtable.Add(3,21);
//删除 --只能通过键来删除
hashtable.Remove(1);
hashtable.Remove("name");

//清空
hashtable.Clear();

//查看 找不到为空
hashtable;
hashtable["name"];

//验证是否存在
if(hashtable.Contains("name"))
{
   //根据键去查找
}
if(hashtable.ContainsKey("name"))
{
    //根据键去查找
}
if(hashtable.ContainsValue("TonyChang"))
{
    //根据值去查找
}
//只能通过键来找值,反之不行

//遍历
hashtable.Count;//键值对数
//不一定按照插入顺序打印
//元素是无序的
foreach(object item in hashtable.Keys)
{
    Console.WriteLine("键"+item);
    Console.WriteLine("值"+hashtable);
}
//遍历值
foreach(object item in hashtable.Values)
{
    Console.WriteLine("值"+item);
}
//键值对遍历
foreach(DictionaryEntry item in hashtable)
{
    Console.WriteLine("键"+item.Key+" 值"+item.Value);
}
//迭代器遍历
IDictionaryEnumerator tcIDE=hashtable.GetEnumerator();
bool flag =tcIDE.MoveNext();
while(flag)
{
   Console.WriteLine("键"+tcIDE.Key+" 值"+tcIDE.Value);
   flag =tcIDE.MoveNext();
}
//存在装箱拆箱泛型约束

泛型约束:关键字 where

[*]值类型whereT :struct
[*]引用类型where T :class
[*]存在无参公共构造函数 where T :new ()
[*]某个类本身或者其派生类 where T:类名
[*]某个接口的派生类型      where T:接口名
[*]另一个泛型类型本身或者派生类型 where T:另一个泛型字符
注:这里的”T“ 可以换成其它的泛型字母
//泛型
class TestClass<T>
{
    public T value;
}
TestClass<int> t=new TestClass<int>();
t.value=666;

//泛型占位符可以有多个
class TestClass2<T1,T2,K,M>
{
    public T1 value1;
    public T2 value2;
    public K value3;
    public M value4;
}
interface ITest<T>
{
    T Value
    {
      get;
      set;
    }
}
//继承之后需要表明具体类类型
class Demo:ITest<int>
{
    public int Value
    {
      get;
      set;
    }
}

//泛型方法
class Test2
{
    public void TestFun<T>(T value)
    {
      Console.WriteLine(value);
    }
    public void TestFun<T>()
    {
      T t=default(T);
    }
    //作为返回值
    public T fun3<T>()
    {
      return default(T);
    }
}

Test2 tt=new Test2();
tt.TestFun<string>("Tony");

//泛型类中的泛型方法
class Test2<T>
{
    public T value;
    public void TestFun(T value)
    {
      //这是非泛型方法
    }
    //泛型方法
    //判断"<>"有无
    public void fun4<K>(K value)
    {
      //打印      
    }
}常用的泛型数据结构类

list

本质:泛型数组
//泛型类型的约束
class Test<T> where T:struct
{
    public void fun1<M> where M:struct
    {
      
    }
}

class Test1<T> where T:class
{
    public void fun1<M> where M:struct
    {
      
    }
}
//注意抽象类的无参公共构造函数
//也被允许
class Test2<T> where T:new()
{
    public void fun1<M> where M:struct
    {
      
    }
}
//······
//约束的组合使用
class Test7<T> where T:class,new ()
{
   
}
//多个泛型有有约束
class Test8<T,K> where T:class,new() where K:struct
{
   
}闭包:
内层函数可以引用包含在它外层函数的变量,即便外层函数的执行已经终止。
注意:该变量的值并非创建变量时候的初始值,而是在外层函数处理过的最终值。
//List
List<int> list=new List<int>();
//添加
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
//查
list;
//清空
list.Clear();
//移除
list.RemoveAt(1);
//查看某个元素是否存在
if(list.Contains(1))
{
        //该元素存在   
}
//查找元素索引
//未找到返回-1
int index=list.IndexOf(4);
//反向查找
//未找到返回-1
index=list.LastIndexOf(4);
//改
list=66;

//插入
list.Insert(0,666);
//遍历
//长度
list.Count;
//容量
list.Capacity;
for(int i=0;i<list.Count;i++)
{
    //打印
    Console.WriteLine(list);
}
foreach(int item in list)
{
   Console.WriteLine(item);
}
//List指定类型 不存在装箱拆箱List排序

//Dictionary
//声明
Dictionary<int,string> dictionary=new Dictionary<int,string>();
//增
dictionary.Add(1,"Hello");
dictionary.Add(2,"World");
dictionary.Add(3,"Tony");
dictionary.Add(4,"Chang");
//删除
dictionary.Remove(1);
//清空
dictionary.Clear();
//查
//按键进行查
dictionary;
dictionary;//找不到则报错!!!
//查看是否存在
if(dictionary.ContainsKey(1))
{
    //存在
}
if(dictionary.ContainsValue("Tony"))
{
    //存在
}
//改
dictionary="258";
//遍历
dictionary.Count;//元素个数
foreach(int item in dictionary.Keys)
{
    Console.WriteLine(item);
    Console.WriteLine(dictionary);
}
//遍历所有类型的值
foreach(int item in dictionary.Values)
{
    Console.WriteLine(item);
}
//键值对一起查找
foreach(KeyValuePair<int,string> item in dictionary)
{
    Console.WriteLine("键:"+item.Key+"值:"+item.Value);
}多线程

进程?
进程是运行中的程序,系统进行资源分配和调度的基本单位,是操作系统的基础。
线程?
线程存在于进程中,是进程中的实际运作单位,是操作系统能够进行运算调度的最小单位。一个进程中可以并发多个线程,他们共享利用进程中的堆栈资源。
多线程?
一个进程中除了必要的主线程之外,可以开启其它的线程来完成一些计算处理。
一个进程中除了必要的主线程之外,可以开启其它的线程来完成一些计算处理。
//简单的单向链表
//节点类
class LinkedNode<T>
{
    public T value;
    public LinkedNode<T> nextNode;
    public LinkedNode(T value)
    {
      this.value=value;
    }
}
//单向链表的简单实现
class LinkdedList<T>
{
    public LinkedNode<T> head;
    public LinkedNode<T> last;
    public void Add(T value)
    {
      LinkedNode<T> node=new LinkedNode<T>(value);
      if(head==null)
      {
            head=node;
            last=node;
      }
      else
      {
            last.nextNode=node;
            last=node;
      }
    }
    public void Remove(T value)
    {
      if(head==null)
      {
            return;
      }
      if(head.value.Equals(value))
      {
            //如果只有一个节点
            //且还是要删除的节点
            head=head.nextNode;
            if(head==null)
            {
                last==null;
            }
            return;
      }
      LinkedNode<T> node=head;//哨兵节点
      //走到目标节点前的一个节点
      while(node.nextNode!=null)
      {
            if(node.nextNode.value.Equals(value))
            {
                break;
            }
            node=node.nextNode;
      }
      //进行移除
      node.nextNode=node.nextNode.nextNode;
    }
}预处理器指令

预处理是在源程序编译成目标指令之前,可以简单的帮助选择一些条件是否要编译执行。
常见的预处理指令:
//双向链表
LinkedList<int> linkedList=new LinkedList<int>();

//增
//从尾部添加
linkedList.AddLast(10);
//从头部加
linkedList.AddFirst(5);

//移除
linkedList.RemoveFirst();//移除头节点
linkedList.RemoveLast();//移除尾节点
//移除元素
linkedList.Remove(5);

//清空
linkedList.Clear();

//查
//头节点
LinkedListNode<int> first=linkedList.First;
//尾节点
LinkedListNode<int> last=linkedList.Last;

//找到某个节点
LinkedListNode<int> node=linkedList.Find(5);//找不到返回为null
//在某个节点之后添加一个节点
linkedList.AddAfter(node,15);
//在某个节点之后前添加一个节点
linkedList.AddBefore(node,12);

//判断某一元素是否存在
if(linkedList.Contains(5))
{
    //链表中存在5
}

//改
//找到某一节点
//改变其数值
//找到某个节点
LinkedListNode<int> node1=linkedList.Find(5);//找不到返回为null
node1.Value=15;

//遍历
foreach(int item in linkedList)
{
    //打印节点
    Console.WriteLine(item);
}

//从头节点进行遍历查找
LinkedListNode<int> curNode=linkedList.First;
while(curNode!=null)
{
        Console.WriteLine(curNode.Value);
    curNode=curNode.Next;
}
//从尾部节点进行遍历查找
LinkedListNode<int> curNode=linkedList.Last;
while(curNode!=null)
{
        Console.WriteLine(curNode.Value);
    curNode=curNode.PreVious;
}反射和特性

反射:

程序正在运行时候,可以查看其它程序集或者自身的元数据。一个运行的程序查看本身或者其它程序的元数据的行为就叫反射。
我们知道,程序=数据+算法,程序在执行过程中需要不断地给它“投喂”数据养料,而反射就是获取养料(类、函数,变量等)的过程。有了反射,在运行时候可以动态的获取自身所需要的资源,可以提高程序的拓展性和灵活性。
程序集:
程序集是经由编译器编译得到的,供进一步编译执行的那个中间产物。在WINDOWS系统中,它一般表现为后缀为·dll(库文件)或者是·exe(可执行文件)的格式。
也就是说程序集是我们开发的项目中程序的集合,工程文件编译运行所需要执行的所有文件资源都算作程序集中的内容。
元数据:
元数据就是用来描述数据的数据,例如在程序中,类、函数、变量等等信息就是程序的元数据,她们保存在程序集中。
Type:
它是反射功能的基础,访问元数据的主要方式.
Assembly
//Type//获取Type//1 objet中的方法int a=45;Type type=a.GetType();//2通过typeof获取Type type2=typeof(int);//3通过类名字//要说明类所在的命名空间Type type3=Type.GetType("System.Int32");//====三个访问方式得到的Type类型相同//得到类的程序集的信息 AssemblyConsole.WriteLine(type.Assembly);Console.WriteLine(type2.Assembly);Console.WriteLine(type3.Assembly);//===========================class Test{    private int i=1;    private int j=2;    private string name;    public Test(int i)    {      this.i=i;    }    public Test(int i,string str):this(i)    {      this.name=str;    }    public void Talk()    {      Console.WriteLine("123");    }}//获取类中所有的公共成员Type type=typeof(Test);MemeberInfo[] infos=type.GetMembers();for (int i = 0; i < infos.Length; i++){    Console.WriteLine(infos);}//获取所有的构造函数ConstructorInfo[] ctors=type.GetConstructors();for(int i=0;i
页: [1]
查看完整版本: C#学习笔记--数据结构、泛型、委托事件等进阶知识点