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.hqwc.cn/news/483626.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二、Vue组件化编程

2、Vue组件化编程 2.1 非单文件组件 <div id"root"><school></school><hr><student></student> </div> <script type"text/javascript">//创建 school 组件const school Vue.extend({template: <div&…

UE4 C++联网RPC教程笔记(三)(第8~9集)完结

UE4 C联网RPC教程笔记&#xff08;三&#xff09;&#xff08;第8~9集&#xff09;完结 8. exe 后缀实现监听服务器9. C 实现监听服务器 8. exe 后缀实现监听服务器 前面我们通过蓝图节点实现了局域网连接的功能&#xff0c;实际上我们还可以给项目打包后生成的 .exe 文件创建…

基于Java+小程序点餐系统设计与实现(源码+部署文档)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

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

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

解决IDEA搜不到插件

File -> Settings -> Plugins https://plugins.jetbrains.com/ 完成以上操作即可搜到插件

week04day02(爬虫02)

<span>: 通常用于对文本的一部分进行样式设置或脚本操作。<a>: 定义超链接&#xff0c;用于创建链接到其他页面或资源的文本。<img>: 用于插入图像。<br>: 用于插入换行。 姓名&#xff1a;<input type"text" value"lisi">…

云呐智能维运技术有哪些?智能运维活动有哪些

智能运维&#xff08;AIOps&#xff09;技术是指利用人工智能、机器学习、大数据分析等先进技术手段&#xff0c;来提高IT运维效率和质量的一系列技术和工具。目前常见的智能运维技术核心功能和应用场景。一些具体的智能运维活动案例&#xff0c;包括但不限于故障预测、自动化修…

【AI链接】 大模型语言模型网站链接

目录 GPT类1. chatgpt2. GROP3. Google AI Studio4. Moonshot AI (国内) 解读论文类&#xff1a;1. txyz 编程辅助插件&#xff1a;1. Fitten Code GPT类 1. chatgpt https://chat.openai.com/ 2. GROP https://groq.com/ 3. Google AI Studio https://aistudio.google…

Pytorch 复习总结 3

Pytorch 复习总结&#xff0c;仅供笔者使用&#xff0c;参考教材&#xff1a; 《动手学深度学习》Stanford University: Practical Machine Learning 本文主要内容为&#xff1a;Pytorch 多层感知机。 本文先介绍了多层感知机的用法&#xff0c;再就训练过程中经常出现的过拟…

HarmonyOS4.0系统性深入开发36 媒体查询(mediaquery)

媒体查询&#xff08;mediaquery&#xff09; 概述 媒体查询作为响应式设计的核心&#xff0c;在移动设备上应用十分广泛。媒体查询可根据不同设备类型或同设备不同状态修改应用的样式。媒体查询常用于下面两种场景&#xff1a; 针对设备和应用的属性信息&#xff08;比如显…

【关于深度学习的一些资料】

曾梦想执剑走天涯&#xff0c;我是程序猿【AK】 目录 动手学深度学习Awesome Deep LearningTensorFlow Official ModelsPyTorch Image ModelsDeep Reinforcement LearningNeural Style Transfer 动手学深度学习 动手学深度学习 https://zh.d2l.ai/chapter_installation/index.…

【CKA 学员预约考试流程】

CKA 学员预约考试流程 一、获取考试码、 我们需要去 Linux 基金会中文版网页注册账号并根据优惠码获取考试码&#xff0c;步骤如下&#xff1a; 1.复制链接去浏览器打开首页&#xff1a;https://training.linuxfoundation.cn/ 2.接下来点击 注册 3.根据要求 填写注册信息 …