C#知识点-14(索引器、foreach的循环原理、泛型、委托)

索引器

概念:索引器能够让我们的对象,以索引(下标)的形式,便捷地访问类中的集合(数组、泛型集合、键值对)
应用场景:
1、能够便捷地访问类中的集合
2、索引的数据类型、个数、顺序不固定的时候
索引器与数组的比较:
        索引器的索引值(index)类型不受限制
索引器与属性的比较:
        a、索引器可以被重载,属性不能
        b、索引器不能声明为static,属性可以

    internal class Program{static void Main(string[] args){Person p = new Person();Console.WriteLine(p[0]);Console.WriteLine(p[1]);p[2] = "张飞";Console.WriteLine(p[2]);Console.WriteLine(p["张三"]);Console.WriteLine(p["李四"]);p["王五"] = 100;Console.WriteLine(p["王五"]); ;Console.ReadKey();Console.ReadKey();}}class Person{//私有字段存储数组private string[] names = { "张三", "李四", "王五", "赵六", "田七" };//键值对private Dictionary<string, int> dic = new Dictionary<string, int>();//在构造函数里给键值对添加数据public Person(){dic.Add("张三", 1);dic.Add("李四", 2);dic.Add("王五", 3);dic.Add("赵六", 4);}//索引器//string:表示通过索引器获取数据的类型//this:表示索引器的名字,必须是this,不能修改//index:索引的类型public string this[int index]{get { return names[index]; }//通过索引取得数组中的值set { names[index] = value; }//给数组中的某个元素赋值}//索引器是可以重载的public int this[string key]{get { return dic[key]; }set { dic[key] = value; }}}

索引器案例

    internal class Program{//根据员工的姓名、编号,查找员工所在部门。//根据员工的姓名、部门,查找员工的编号。//根据员工的部门、编号,查找员工的姓名。static void Main(string[] args){EmployeeIndexer emps = new EmployeeIndexer();string dep = emps["张三", 1];if (!string.IsNullOrEmpty(dep)){Console.WriteLine(dep);}else{Console.WriteLine("查无此人");}int? id = emps["李四", "研发部"];if (id != null){Console.WriteLine(id);}else{Console.WriteLine("查无此人");}Console.ReadKey();}class Employee  //员工类{public string Name { get; set; } //员工姓名public int ID { get; set; } //员工编号public string Department { get; set; }  //员工部门public Employee(string name, int iD, string department){this.Name = name;this.ID = iD;this.Department = department;}}class EmployeeIndexer   //员工的索引类,负责对员工信息进行精确的查询{private List<Employee> listEmps = new List<Employee>();public EmployeeIndexer(){listEmps.Add(new Employee("张三", 1, "行政部"));listEmps.Add(new Employee("李四", 2, "财务部"));listEmps.Add(new Employee("王五", 3, "研发部"));listEmps.Add(new Employee("赵六", 4, "人事部"));}//根据员工的姓名、编号,查找员工所在部门。public string this[string name,int id]{get{for (int i = 0; i < listEmps.Count; i++){if (listEmps[i].Name == name && listEmps[i].ID==id){return listEmps[i].Department;}}return null;}}//根据员工的姓名、部门,查找员工的编号。public int? this[string name, string dep]  // int?  ? 可空的值类型{get{for (int i = 0; i < listEmps.Count; i++){if (listEmps[i].Name == name && listEmps[i].Department == dep){return listEmps[i].ID;}}return null;}}//根据员工的部门、编号,查找员工的姓名。public string this[int id, string dep]{get{for (int i = 0; i < listEmps.Count; i++){if (listEmps[i].ID == id && listEmps[i].Department == dep){return listEmps[i].Name;}}return null;}}}}

foreach的循环原理

1、要被循环的对象,需要实现IEnumerable接口
2、需要给被循环的对象,创建一个遍历的对象,并且要实现IEnumerator接口
3、        Current:返回当前遍历到的数据元素
              MoveNext:判断时候可以继续向后循环,并改变index的值
              Reset:重置索引

通过代码实现foreachinternal class Program{//foreach的循环原理//只有实现了IEnumerable这个接口的对象才能被foreachstatic void Main(string[] args){Person p = new Person();//获取遍历Person对象的人IEnumerator enumerator = p.GetEnumerator();//开始遍历while (enumerator.MoveNext()){Console.WriteLine(enumerator.Current.ToString());}//IEnumerable :要被遍历的对象必须实现这个接口//IEnumerator: 遍历对象的迭代器对象,要实现Console.ReadKey();//或者可以直接使用foreachforeach (var item in p){Console.WriteLine(item);}Console.ReadKey();}}class Person : IEnumerable{//IEnumerable : 接口,表示可以被foreach遍历的能力//IEnumerator:真正做遍历集合这件事儿的人//GetEnumerator:获取做遍历集合这件事儿的人private string[] names = { "张三", "李四", "王五", "赵六", "田七" };public IEnumerator GetEnumerator(){return new PersonEnumerator(names);}}//枚举/迭代/遍历class PersonEnumerator : IEnumerator{string[] myNames;int index = -1;//构造函数:获取要遍历的真实数据public PersonEnumerator(string[] names){this.myNames = names;}//Current表示返回当前遍历到的元素,object类型public object Current{//索引没有越界的情况get{if (index>=0&&index<this.myNames.Length){return this.myNames[index];}return null;//数组越界了}}//1、索引+1//2、判断是否可以继续向后移动(+1),//如果可以继续向后+1.则索引+1,并且返回true//如果不可以向后+1,返回falsepublic bool MoveNext(){if (index+1<this.myNames.Length){index++;return true;}else{return false;}}//重置索引,让索引回到原始位置public void Reset(){index= -1;}}

泛型

概念:在某些情况,我们不想使用特定的数据类型,可以使用泛型

    internal class Program{static void Main(string[] args){Person<int> person = new Person<int>();person.SayHi(199);Person<string> person2 = new Person<string>();person2.SayHi("张三");Person<double> person3 = new Person<double>();person3.SayHi_2<string>(3.14, "李四");person3.SayHi_2(3.14);double d = person3.SayHi_3(11.11);Console.WriteLine(d);int n = person3.SayHi_4<int>(3.14, 100);Console.WriteLine(n);int n2 = person3.SayHi_5<int>(3.14);Console.WriteLine(n2);Console.ReadKey();}}//泛型类class Person<T>{public void SayHi(T t){Console.WriteLine(t);}//泛型方法public void SayHi_2<K>(T t, K k){Console.WriteLine(t);Console.WriteLine(k);}//泛型方法也可以重载public void SayHi_2(T t){Console.WriteLine(t);}//返回值类型为T,参数为Tpublic T SayHi_3(T t){return t;}//返回值类型为K,参数为T和Kpublic K SayHi_4<K>(T t, K k){return k;}//返回值类型为K,参数为Kpublic K SayHi_5<K>(K k){return k;}//泛型方法中的返回值如何处理?//1、使用typeof关键字判断泛型的类型//2、使用object作为中间量进行强制转换//3、return defalut。default会返回数据类型的默认值public K SayHi_5<K>(T t){K k;//如果k的类型是intif (typeof(K) == typeof(int)){return (K)(object)100;}else if (typeof(K) == typeof(string)){return (K)(object)"Hello World";}else if (typeof(K) == typeof(double)){return (K)(object)3.14;}else{//返回K类型的默认值return default;}}//泛型接口interface IFlayble<T>{void Fly(T t);}class Plane : IFlayble<string>{public void Fly(string t){throw new NotImplementedException();}}class Bird : IFlayble<int>{public void Fly(int t){throw new NotImplementedException();}}}

泛型约束

    internal class Program{static void Main(string[] args){Person<int> person = new Person<int>();Student<Person<int>> student2 = new Student<Person<int>>();Teacher<Animal> t1 = new Teacher<Animal>();Teacher<Bird> t2 = new Teacher<Bird>();Plane<IFly> plane = new Plane<IFly>();Plane<MaQue> p2 = new Plane<MaQue>();Computer<int, IComparable> cpu = new Computer<int, IComparable>();Computer<FileStream, Stream> cpu2 = new Computer<FileStream, Stream>();}}//泛型约束//where 表示类型要符合的条件class Person<T> where T : struct  //值类型约束{}class Student<T> where T : class, new()        //引用类型约束{}class Animal { }class Bird : Animal { }interface IFly{void Fly();}class MaQue : IFly{public void Fly(){}}class Teacher<T> where T : Animal { }class Plane<T> where T : IFly { }class Computer<T, U> where T : U { }

委托

概念:把方法作为参数,传递给另一个方法
委托,就是一个方法的指针
声明委托:public delegate(委托的关键字) 返回值类型 委托名称(参数列表)
使用委托:创建委托对象,指向某一个跟委托签名一致的方法(签名:参数和返回值)
 

    internal class Program{public delegate void Del();//无参数无返回值的委托public delegate void Del2(string name);//参数为string的委托public delegate int Del3(string name, int age);//有两个参数,返回值为int类型的委托static void Main(string[] args){//虽然在代码层面没有创建委托对象,但是编译器在编译的时候,依然会帮助我们创建一个委托对象//这个委托对象,在内存中指向M1方法Del del = M1;//等同于 Del del = new Del(M1);del(); //对M1方法的直接调用del.Invoke();//对方法的间接调用Del2 del2 = M2;del2("张三");del2.Invoke("李四");Del3 del3 = M3;//委托与他指向的方法签名,必须完全一致,M4的话会报错int res = del3("张三", 18);Console.WriteLine(res);Console.ReadKey();}static void M1(){Console.WriteLine("无参数无返回值的方法");}static void M2(string name){Console.WriteLine("参数string,无返回值的方法");Console.WriteLine(name);}static int M3(string name,int age){Console.WriteLine("两个参数,返回值为int的方法");Console.WriteLine(name);Console.WriteLine(age);return 100;}static int M4(int age,string name){Console.WriteLine("和上面方法的参数类型不同");return 200;}}

委托案例


{public delegate string DelProStr(string str);internal class Program{static void Main(string[] args){//处理字符串数组//1、给字符串数组的两边,添加双引号//2、给字符串数组全部转换为大写//3、给字符串数组全部转换为小写string[] names = { "Jay", "James", "green", "blue" };//SYH(names);//StrToUpper(names);//StrToLower(names);ProcessStr(names, StrToSYH);ProcessStr(names, StrToUpper);foreach (var item in names){Console.WriteLine(item);}Console.ReadKey();}static void ProcessStr(string[] names, DelProStr del){for (int i = 0; i < names.Length; i++){names[i] = del(names[i]);}}static string StrToSYH(string str){return "\"" + str + "\"";}static string StrToUpper(string str){return str.ToUpper();}static string StrToLower(string str){return str.ToLower();}把数组中的每一个元素,加双引号//static void SYH(string[] names)//{//    for (int i = 0; i < names.Length; i++)//    {//        names[i] = "\"" + names[i] + "\"";//    }//}把数组中的每一个元素,转成大写//static void StrToUpper(string[] names)//{//    for (int i = 0; i < names.Length; i++)//    {//        names[i] = names[i].ToUpper();//    }//}把数组中的每一个元素,转成小写//static void StrToLower(string[] names)//{//    for (int i = 0; i < names.Length; i++)//    {//        names[i] = names[i].ToLower();//    }//}}
}

使用委托计算两个数的最大值


{public delegate int DelCompare<T>(T o1, T o2); //比较o1和o2的值  让o1-o2  >  0internal class Program{static void Main(string[] args){//求数组的最大值  int  string  Personint[] numbers = { 1, 2, 3, 43, 45 };string[] names = { "ab", "James", "abcdefg" };Person[] pers = { new Person() { Name = "张三", Age = 19 }, new Person() { Name = "李四", Age = 20 }, new Person() { Name = "王五", Age = 22 } };int max = GetMax(numbers, GetIntMax);string max2 = GetMax(names, GetStringMax);Person max3 = GetMax(pers, GetPersonMax);Console.WriteLine(max3.Name);Console.WriteLine(max2);Console.ReadKey();}static T GetMax<T>(T[] nums, DelCompare<T> del)  //不同点1:返回值不一样  不同点2:参数不一样  不同点3:比较的方式不一样{T max = nums[0];for (int i = 0; i < nums.Length; i++){//nums[i] > maxif (del(nums[i], max) > 0) //比较的方式,因为要比较的数据类型是不一样的,所以比较的方式也是不一样的。{max = nums[i];}}return max;}static int GetIntMax(int o1, int o2){//值类型---->引用类型:装箱   //int n1 = (int)o1;//int n2 = (int)o2;return o1 - o2;}static int GetStringMax(string o1, string o2){//string s1 = (string)o1;//string s2 = (string)o2;return o1.Length - o2.Length;}static int GetPersonMax(Person o1, Person o2){//Person p1 = (Person)o1;//Person p2 = (Person)o2;return o1.Age - o2.Age;}//求整数类型数组的最大值//static int GetMax(int[] nums)  //不同点1:返回值不一样  不同点2:参数不一样  不同点3:比较的方式不一样//{//    int max = nums[0];//    for (int i = 0; i < nums.Length; i++)//    {//        if (nums[i] > max)//        {//            max = nums[i];//        }//    }//    return max;//}求字符串数组的最大值(字符串的长度)//static string GetMax(string[] names)//{//    string max = names[0];//    for (int i = 0; i < names.Length; i++)//    {//        if (names[i].Length > max.Length)//        {//            max = names[i];//        }//    }//    return max;//}求Person数组中,年龄最大的人//static Person GetMax(Person[] pers)//{//    Person max = pers[0];//    for (int i = 0; i < pers.Length; i++)//    {//        if (pers[i].Age > max.Age)//        {//            max = pers[i];//        }//    }//    return max;//}}class Person{public int Age { get; set; }public string Name { get; set; }}
}

使用lambda表达式简化上述代码

    public delegate int DelCompare<T>(T o1, T o2);//比较o1和o2的值internal class Program{static void Main(string[] args){//求数组的最大值 int string Personint[] numbers = { 1, 2, 3, 4, 5 };string[] names = { "ab", "abc", "avcdsf" };Person[] pers = { new Person() { Name = "张三", Age = 18 }, new Person() { Name = "李四", Age = 20 }, new Person() { Name = "王五", Age = 25 } };//调用泛型方法int intMax = GetMax<int>(numbers, (a, b) => { return a - b; });//lambda表达式:方法的极致的简化写法Console.WriteLine(intMax);string stringMax = GetMax(names, (a, b) => { return a.Length-b.Length; });//如果后面的参数,都是并且只有一个T,则<>可以省略,当你填入第一个参数的时候,所有的T就已经确定了Console.WriteLine(stringMax);Person personMax = GetMax(pers, (a, b) => { return a.Age-b.Age; });Console.WriteLine(personMax.Name);Console.ReadKey();}//写一个泛型方法,用于计算任意类型数组的最大值static T GetMax<T>(T[]nums,DelCompare<T> del){T max = nums[0];for (int i = 0; i < nums.Length; i++){if (del(nums[i],max)>0){max = nums[i];}}return max;}}class Person{public int Age { get; set; }public string Name { get; set;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1113343.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

IDEA 2021.3激活

1、打开idea&#xff0c;在设置中查找Settings/Preferences… -> Plugins 内手动添加第三方插件仓库地址&#xff1a;https://plugins.zhile.io搜索&#xff1a;IDE Eval Reset 插件进行安装。应用和使用&#xff0c;如图

harmony 鸿蒙安全和高效的使用N-API开发Native模块

简介 N-API 是 Node.js Addon Programming Interface 的缩写&#xff0c;是 Node.js 提供的一组 C API&#xff0c;封装了V8 引擎的能力&#xff0c;用于编写 Node.js 的 Native 扩展模块。通过 N-API&#xff0c;开发者可以使用 C 编写高性能的 Node.js 模块&#xff0c;同时…

Linux篇:开发工具yum/vim/gcc/g++/Makefile/gdb

一. yum&#xff1a;软件包管理器 什么是软件包&#xff1f; 在Linux 下安装软件 , 一个通常的办法是下载到程序的源代码 , 并进行编译 , 得到可执行程序 . 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好 , 做成软件包 (可以理解成windows 上的安装程序) 放在…

【Vuforia+Unity】AR05-实物3D模型识别功能实现

对于3D物体的识别&#xff0c;可以是虚拟的也可以是实物的&#xff0c;但是对于虚拟的三维模型意义不大&#xff0c;我们完全可以把三维模型放在屏幕上截一张图&#xff0c;以图片识别的方式召唤数字内容&#xff0c;不过在虚拟现实中或许有用。 因此本文探讨的技术路线主要是…

网络安全“三保一评”深度解析

“没有网络安全就没有国家安全”。近几年&#xff0c;我国法律法规陆续发布实施&#xff0c;为承载我国国计民生的重要网络信息系统的安全提供了法律保障&#xff0c;正在实施的“3保1评”为我国重要网络信息系统的安全构筑了四道防线。 什么是“3保1评”&#xff1f; 等保、分…

Java并发基础:原子类之AtomicBoolean全面解析

本文概要 AtomicBoolean类优点在于能够确保布尔值在多线程环境下的原子性操作&#xff0c;避免了繁琐的同步措施&#xff0c;它提供了高效的非阻塞算法实现&#xff0c;可以大大提成程序的并发性能&#xff0c;AtomicBoolean的API设计非常简单易用。 AtomicBoolean核心概念 …

STM32 TIM2重映射

STM32定时器 文章目录 STM32定时器[TOC](文章目录) 前言一、问题分析二、代码 前言 最近想弄一个多路输出PWM&#xff0c;但是发现TIM2不能用&#xff0c;根据手册也对它进行重映射了&#xff0c;但是还是不能用&#xff0c;用示波器发现驱动能力比较弱&#xff0c;然后禁用jt…

jvm垃圾收集器-三色标记算法

1.对象已死吗? 在堆里面存放着Java世界中几乎所有的对象实例&#xff0c;垃圾收集器在对堆进行回收前&#xff0c;第一件事情就是要确定这些对象之中哪些还“存活”着&#xff0c;哪些已经“死去”&#xff08;即不可能再被任何途径使用的对象). 引计数法 引用计数算法是一…

打造个性化电子画册,提升品牌魅力

​个性化电子画册可以根据不同的用户群体&#xff0c;提供不同的内容。企业可以根据目标客户的特点&#xff0c;为他们定制不同的内容&#xff0c;如产品介绍、品牌故事、企业文化等。这样不仅可以吸引更多的用户关注&#xff0c;还可以增强用户对品牌的信任度。 但是怎么制作电…

【Linux基础】vim、常用指令、组管理和组权限

Linux基础 1、目录结构2、vi和vim3、常用指令运行级别找回密码帮助指令时间日期指令搜索查找文件目录操作磁盘管理指令压缩和解压缩 4、组管理和组权限用户操作指令权限 1、目录结构 Linux的文件系统是采用级层式的树状目录结构&#xff0c;在此结构中的最上层是根目录“/”&a…

【设计模式】01-装饰器模式Decorator

作用&#xff1a;在不修改对象外观和功能的情况下添加或者删除对象功能&#xff0c;即给一个对象动态附加职能 装饰器模式主要包含以下角色。 抽象构件&#xff08;Component&#xff09;角色&#xff1a;定义一个抽象接口以规范准备接收附加责任的对象。具体构件&#xff08…

qt-OPENGL-星系仿真

qt-OPENGL-星系仿真 一、演示效果二、核心程序三、下载链接 一、演示效果 二、核心程序 #include "model.h"Model::Model(QOpenGLWidget *_glWidget) { glWidget _glWidget;glWidget->makeCurrent();initializeOpenGLFunctions(); }Model::~Model() {destroyV…

hung task, soft lockup, hard lockup, workqueue stall

hung task&#xff0c;soft lockup&#xff0c;hard lockup&#xff0c;workqueue stall 是 linux 内核中的异常检测机制&#xff0c;这 4 个检测均是通过时间维度上的检测来判断异常。 在时间维度上的检测机制&#xff0c;有两个核心的点&#xff1a; &#xff08;1&#xff…

【ubuntu2004安装N卡驱动】

软硬件环境 硬件&#xff1a;联想notebook16&#xff0c;显卡4060laptop 软件&#xff1a; ubuntu20.04 驱动安装成功的版本&#xff1a;NVIDIA-Linux-x86_64-535.146.02.run 使用默认的驱动安装&#xff0c;没用原因如下 让手动安装。 手动安装 环境准备&#xff1a; sudo …

Unity NavMesh 清除不可行走区域

通常场景中物体设置为static或Navigation Static后&#xff0c;打开Navigation使用默认设置烘焙NavMesh&#xff0c;模型顶部和底部会出现蓝色网格&#xff0c;但其中有部分属于不可能到达区域&#xff0c;如下图 本文介绍两种可去掉NavMesh中不需要网格的方法&#xff1a; 方…

LInux-信号1

文章目录 前言一、信号是什么&#xff1f;二、学习步骤使用kill -l命令查看信号列表可以看到有那么多信号&#xff0c;那么进程是如何识别这么多信号的呢&#xff1f; 使用kill命令终止进程信号的捕捉kill函数raise函数abort函数 Core dump如何查看自己的核心转储功能是否被打开…

【项目管理】CMMI-质量保证过程

质量保证过程&#xff08;PQA)&#xff1a;通过质量保证活动&#xff0c;确保过程与产品满足过程、规程及相应的要求&#xff0c;确保问题得到关注与解决&#xff0c;使工作人员和管理者能够客观地了解过程与相关的工作产品。QA工程师应实施质量保证策划活动&#xff0c;客观地…

面向对象编程入门:掌握C++类的基础(1/3)

面向对象编程&#xff08;OOP&#xff09;是一种编程范式&#xff0c;它使用“对象”来设计软件。在C中&#xff0c;类是创建对象的蓝图。本文将介绍类的基本概念&#xff0c;帮助初学者理解如何在C中使用类来实现面向对象编程。 ​​​​​​​ 1. 类的引入 在深入探讨类的…

类之间的关系详解

在面向对象编程中&#xff0c;类之间的关系是构建和理解软件设计的基础。这些关系主要包括关联、聚合、合成、依赖、继承和实现。下面通过具体的例子和Java代码示例来说明这些关系。 1. 关联&#xff08;Association&#xff09; 关联关系表示两个类之间的结构化关系&#xff…

170基于matlab的DNCNN图像降噪

基于matlab的DNCNN图像降噪&#xff0c;网络分为三部分&#xff0c;第一部分为ConvRelu&#xff08;一层&#xff09;&#xff0c;第二部分为ConvBNRelu&#xff08;若干层&#xff09;&#xff0c;第三部分为Conv&#xff08;一层&#xff09;&#xff0c;网络层数为17或者20层…