漯河网站建设zrgu,网站建设高清图,网站版建设,深圳做网站哪家公司比较好而且不贵文章目录 泛型泛型的使用泛型的约束委托委托的实例化多播委托委托的调用内置委托类型委托练习泛型委托Lambda表达式(进阶)上期习题答案本期习题 泛型
泛型#xff08;Generic#xff09; 是一种规范#xff0c;它允许我们使用占位符来定义类和方法#xff0c;编译器会在编… 文章目录 泛型泛型的使用泛型的约束委托委托的实例化多播委托委托的调用内置委托类型委托练习泛型委托Lambda表达式(进阶)上期习题答案本期习题 泛型
泛型Generic 是一种规范它允许我们使用占位符来定义类和方法编译器会在编译时将这些占位符替换为指定的类型利用泛型的这一特性我们可以定义通用类泛型类,方法泛型方法,接口(泛型接口)。
泛型:广泛的类型,一般用于传递类型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace _01_泛型
{internal class Program{static void Main(string[] args){//泛型:广泛的类型,一般用于传递类型// 中间的类型就是传入的泛型Listint list new Listint();Dictionarystring,int keyValuePairs new Dictionarystring,int();//调用的时候,通过将类型的实参进行传递,对应位置的泛型形参就是这个类型了Fntint(1);Fntstring(2);Fntdouble(1.1);Fntint(1, new int[] { 1, 2 });Fntstring(a, new string[] { a, b });Fntint, string(1, a);//泛型可以根据传入的实参,自动推断泛型的类型Fnt(1);//自动推断泛型为intFnt(2);//自动推断泛型为string}//泛型的命名规范,一般以T开头的单词命名,尽量能表示这个类型的作用,如果使用一个字母作为泛型,建议使用T//也就是说,多个字母的时候 使用TXxxx 单独的字母的时候使用T//泛型在方法中的使用//在方法名的后面添加 里面就相当于是类型的形参列表public static T FntT(T a, T[] arrA){return a;}public static void FntTTest1,TTset2(TTest1 a, TTset2 b ){}//接收一个任意类型的数据,转换为对应长度的数组,其中存放对应的数据public static T[] FntsT(T value,int count){T[] resnew T[count];for (int i 0; i count; i){res[i] value;}return res;}}//需求: 实现一个方法 这个方法接收一个int类型,返回一个int类型,接收string 返回string...class Test{public int Fn(int value){return value;}public string Fn(string value){return value;}}public static T FntT(T a) //用泛型{return a;}}
泛型的使用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace _02_泛型的使用
{internal class Program{static void Main(string[] args){Liststring list new Liststring();Peopleint, string p1 new Peopleint, string();p1.A 1;p1.B a;p1.Fnchar(c, 3, zifuchuan);p1.Fn(c, 3, zifuchuan);Peopleint, int p2 new Peopleint, int();}}
}//--------- 泛型类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace _02_泛型的使用
{//给类添加泛型internal class PeopleTTest1,TTest2{//定义一个属性 类型为TTest1类型public TTest1 A { get; set; }public TTest2 B { get; set; }public void FnT(T a,TTest1 b,TTest2 c){}}
}//------------泛型接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace _02_泛型的使用
{//泛型接口internal interface IBook1T{T A { get; set; }T B { get; set; }ListT C { get; set; }T[] Fn(T a);}class Book : IBook1int{public int A { get ; set ; }public int B { get throw new NotImplementedException(); set throw new NotImplementedException(); }public Listint C { get throw new NotImplementedException(); set throw new NotImplementedException(); }public int[] Fn(int a){throw new NotImplementedException();}}class Book2 : IBook1string{public string A { get throw new NotImplementedException(); set throw new NotImplementedException(); }public string B { get throw new NotImplementedException(); set throw new NotImplementedException(); }public Liststring C { get throw new NotImplementedException(); set throw new NotImplementedException(); }public string[] Fn(string a){throw new NotImplementedException();}}}
泛型的约束
默认泛型是没有约束的,可以传递任意类型的数据
声明带有泛型的方法或者类的时候,可以对泛型添加约束,让这个泛型不那么广泛 public void Fn2(T v) where T:struct //T 只能是值类型where T : class //T只能是引用类型where T : new() 必须是一个类,并且必须拥有无参构造方法必须对泛型进行 where T : new() 约束后 才能进行new操作where T : People //T 必须是People类的派生类where T : IPeople //T 必须是实现了IPeople接口的类,或者是实现了这个接口的类的子类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace _03_泛型的约束
{internal class Program{static void Main(string[] args){//默认泛型是没有约束的,可以传递任意类型的数据Test test new Test();test.Fn1int(1);test.Fn1string(a);test.Fn1int[](new int[] { 1, 2 });test.Fn1People(new People());//只能传递值类型的数据test.Fn2int(1);test.Fn2double(1.1);//test.Fn2string(a);//test.Fn2int[](new int[] { 1, 2 });//test.Fn2People(new People());//只能传递引用类型//test.Fn3int(1);//test.Fn3double(1.1);test.Fn3string(a);test.Fn3int[](new int[] { 1, 2 });test.Fn3People(new People());//只能传递拥有无参构造方法类test.Fn4People(new People());test.Fn5People(new People());test.Fn5Student(new Student()); test.Fn5SamllStudent(new SamllStudent());test.Fn6People(new People());test.Fn6Student(new Student());}class Test{public void Fn1T(T v) { }//声明带有泛型的方法或者类的时候,可以对泛型添加约束,让这个泛型不那么广泛// where T:struct T只能是值类型public void Fn2T(T v) where T : struct { }//where T : class T只能是引用类型public void Fn3T(T v) where T : class { }//where T : new() 必须是一个类,并且必须拥有无参构造方法public void Fn4T(T v) where T : new(){//必须对泛型进行 where T : new() 约束后 才能进行new操作T t new T();}//where T : People T 必须是People类的派生类public void Fn5T(T v) where T : People { }//where T : IPeople T 必须是实现了IPeople接口的类,或者是实现了这个接口的类的子类public void Fn6T(T v) where T : IPeople { }}}interface IPeople{}class People: IPeople{}class Student : People{}class SamllStudent : People{}
}
委托
C# 中的委托Delegate类似于 C 或 C 中函数的指针。委托Delegate 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。(可以理解为是一种数据类型。) 委托Delegate用于实现事件和回调方法。所有的委托Delegate都派生自 System.Delegate 类。
格式:访问修饰符 delegate 方法的返回值类型 委托的名称(方法的参数…) 委托其实就是一个类型,我们可以使用委托创建一个方法的类型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;//声明一个委托,委托的声明只是声明了一个方法的类型
//格式:访问修饰符 delegate 方法的返回值类型 委托的名称(方法的参数....)
public delegate bool MyDelegate(string v);
namespace _04_委托
{internal class Program{static void Main(string[] args){//C#是强类型的编程语言,强类型编程语言的特性是所有的东西都有特定的类型//变量,属性 ,字段...在定义的时候都需要显式的指定他们的类型//方法,之前没有类型,委托其实就是一个类型,我们可以使用委托创建一个方法的类型Test.TestFn(MyFn);}static bool MyFn(string a){Console.WriteLine(这是个函数a);return true;}}class Test{//方法接收一个委托类型的参数,就相当于接收一个方法,该方法必须满足这个委托规定的参数和返回值public static void TestFn(MyDelegate f) {f(吴凡);}}
}
委托的实例化
实例化一个委托的时候必须传递一个方法 MyFns fns1new MyFns(Fn1);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;//1.创建一个委托类型,只能保存没有返回值并且参数为 int和string类型的方法
delegate void MyFns(int v1,string v2);
delegate int NumberOperator(int v1, int v2);
namespace _05_委托的实例化
{internal class Program{static void Main(string[] args){new TestClass();}}class TestClass{public TestClass(){int a 1;//2.实例化一个委托的时候必须传递一个方法MyFns fns1new MyFns(Fn1);Fn1(1, wuyifan);//委托类型的变量,可以将它理解为一个特殊的方法,直接将他当做方法调用即可fns1(1,luozhxinag);//练习: 定义一个委托,接收两个int参数,返回int类型参数,并且创建一个委托类型的变量并调用该委托NumberOperator no new NumberOperator(Add);int num1 Add(10,30);Console.WriteLine(num1);int num2 no(6,8);Console.WriteLine(num2);// NumberOperator no2 new NumberOperator(Cheng// 委托创建可以简写NumberOperator no2 Cheng;Console.WriteLine(no2(2,4));//委托的另外一个调用方法int v no2.Invoke(2, 4);Console.WriteLine(v);}void Fn1(int a, string b){Console.WriteLine($a{a},b{b});}int Add(int a, int b){return a b;}int Cheng(int a, int b){return a * b;}}}
多播委托
包含多个方法的委托,称之为多播委托如果这个委托类型的变量,存储了多个方法,当该委托被调用的时候,将会执行所有的方法并传递参数,用和-进行多播的增加与减少
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;delegate void MyDelegate(string name);
namespace _06_多播委托
{internal class Program{static void Main(string[] args){//包含多个方法的委托,称之为多播委托MyDelegate fns new MyDelegate(Fn1);//使用运算符,在委托变量上添加一个方法fns new MyDelegate(new Test().Fn2);//如果这个委托类型的变量,存储了多个方法,当该委托被调用的时候,将会执行所有的方法并传递参数fns(吴亦凡);//简写MyDelegate fns2 Fn1;fns2 new Test().Fn2;fns2(luozhixinag);MyDelegate fns3 Fn1;fns3 new Test().Fn2;//还可以使用-从委托中移除一个方法fns3 - Fn1;fns3(李云迪);Console.WriteLine(---------------------------);MyDelegate fns4 Fn1;fns4 new Test().Fn2;fns4 - new Test().Fn2;// 这个委托同样会被调用两次, 因为39行和40行操作的不是同一个方法//fns4(郑爽);fns4.Invoke(郑爽);//一下这些代码 等价于 以上代码MyDelegate fns5 Fn1;Test t1new Test();Test t2new Test();fns5 t1.Fn2;fns5 - t2.Fn2;fns5.Invoke(郑爽);Console.WriteLine(-----------------------------);//解决方案1:将对象使用变量保存, 执行和-操作MyDelegate fns6 Fn1;Test tnew Test();fns6 t.Fn2;fns6 - t.Fn2;fns6.Invoke(郑爽2.0);//解决方案2:将要加入委托的函数定义为静态函数,用类名调用MyDelegate fns7 Fn1;fns7 Test.Fn3;fns7 - Test.Fn3;fns7.Invoke(曹云金);}public static void Fn1(string v){Console.WriteLine($这是Fn1中的v:{v});}}class Test{public void Fn2(string v){Console.WriteLine($这是Fn2中的v:{v});}public static void Fn3(string v){Console.WriteLine($这是Fn3中的v:{v});}}
}
委托的调用
委托被调用的时候,会执行该委托变量中存储的所有的方法当委托中没有存储任何方法的时候,执行会报错:未将对象引用设置到对象的实例 ,解决方法—简写为 ?. 运算符 当前面的值为null的时候 不往后执行 ?. 用于从可能为空的值上获取他的属性, 即使该值为null 也不会报错 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace _07_委托的调用
{internal class Program{static void Main(string[] args){Test tnew Test();t.Run();}}class Test{public delegate int MyDealegate(int x);public MyDealegate Fns {get;set; }public Test(){Fns Fn1;Fns Fn2;}public int Fn1(int v){Console.WriteLine(v*10);return v*10;}public int Fn2(int v){Console.WriteLine(v * v);return v * v;}People p;public void Run(){//1.委托被调用的时候,会执行该委托变量中存储的所有的方法//Fns(888);//2.当委托中没有存储任何方法的时候,执行会报错:未将对象引用设置到对象的实例// if (Fns ! null) Fns(7); //简写为 ?. 运算符 当前面的值为null的时候 不往后执行Fns?.Invoke(7);//?. 用于从可能为空的值上获取他的属性, 即使该值为null 也不会报错Console.WriteLine(p?.Namenull);pnew People();p.Name 罗志祥;Console.WriteLine(p?.Name);}}class People{public string Name;}}
内置委托类型
Action 用于指定一些不拥有返回值的委托 例一个接收 int string类型的参数,没有返回值 public static void Fn2(Actionint,string fn) Func 用于指定一些用于返回值的委托 例: 接收int 返回string public static void Fn5(Funcint,string fn) 中最后一个参数为返回值类型 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;//delegate void FnDelegate1();
//delegate void FnDelegate2(int v, string s);
//delegate void FnDelegate3(int v1,int v2);
namespace _08_内置委托类型
{internal class Program{static void Main(string[] args){Test.Fn1(f1);Test.Fn2(f2);Test.Fn3(f3);Test.Fn4(f4);Test.Fn5(f5);//这种形式的创建委托比较麻烦,如果该委托只用一次,当做方法的参数的时候,就显得代码比较臃肿,//c#内置了一些委托, 通过泛型指定他的参数类型//Action Func}static void f1() { }static void f2(int i,string s) { }static void f3(int[] i1, bool[] b2) { }static string f4() { return 123; }static string f5(int i) { return 123; }}class Test{//一个不接收参数,没有返回值//Action 用于指定一些不拥有返回值的委托public static void Fn1(Action fn){}//一个接收 int string类型的参数,没有返回值public static void Fn2(Actionint,string fn){}//一个接收 int[] bool[] 没有返回值public static void Fn3(Actionint[], bool[] fn){}//一个不接收参数 返回string //Func 用于指定一些用于返回值的委托public static void Fn4(Funcstring fn){}//接收int 返回string public static void Fn5(Funcint,stringfn){}//接收int 返回 int public static void Fn6(Funcdouble,int fn){}}
}
委托练习
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace _09_委托练习
{internal class Program{static void Main(string[] args){int[] ints new int[] { 1, 2, 43, 5, 56, 6, 7 };//int num1 Array.Find(ints,Fn2);int num2 FindFrist(ints, Fn2);Console.WriteLine(num2);//自定义Find}public static bool Fn2(int value){return value % 2 0;}public static int FindFrist(int[] ints,Funcint,bool fn){for (int i 0; i ints.Length; i){if (fn(ints[i])true){return ints[i];}}return 0;}}}
泛型委托
当定义一个方法返回值为泛型例如名为T时方法体中可以使用default(T)来返回当前类型的默认值。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;delegate bool CAllBackT(T s);
namespace _10_泛型委托
{internal class Program{static void Main(string[] args){string[] strings { 亦凡1, 吴亦凡2, 罗志祥 };string s FindFirststring(strings, FindWu);int[] ints { 1, 3, 5, 6, 5 };// int iFindFirstint(ints, FindEven);int i FindFirstint(ints, FindEven);Console.WriteLine(i);}static bool FindWu(string name){return name.StartsWith(吴);}static bool FindEven(int value){return value%2 0;}//public static string FindFirst(string[] Arrs, CAllBack fn)//{// for (int i 0; i Arrs.Length; i)// {// if (fn(Arrs[i])true)// {// return Arrs[i];// }// }// return null;//}//public static T FindFirstT(T[] Arrs, CAllBackT fn)//{// for (int i 0; i Arrs.Length; i)// {// if (fn(Arrs[i]) true)// {// return Arrs[i];// }// }// //返回当前类型的默认值// return default(T);//}//最优写法public static T FindFirstT(T[] Arrs, FuncT,bool fn){for (int i 0; i Arrs.Length; i){if (fn(Arrs[i]) true){return Arrs[i];}}//返回当前类型的默认值return default(T);}}
}
Lambda表达式(进阶)
格式:Func参数1的类型,参数2的类型,返回值类型fnName(参数1,参数2){函数的内容}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace _11_Lambda表达式_进阶_
{internal class Program{static void Main(string[] args){int Add(int x,int y){return x y;}//Lambda表达式 用于创建一个函数Console.WriteLine(Add(1,2));Funcint, int, int Add (a, b) {return a b;};fn1(1,吴凡);//格式:Func参数1的类型,参数2的类型,返回值类型fnName(参数1,参数2){函数的内容}Funcint, int, bool fnName1 (int a, int b) {return a b;};//调用的时候和普通的函数相同Console.WriteLine(fnName1(19, 10));//lambda表达式的声明可以简化//1.函数的实现中,参数的类型可以省略Funcint, int, bool fnName2 (a, b) {return a b;};//2.如果只有一个参数,可以省略()Funcint, bool fnName3 a {return a % 2 0;};//3.如果函数中只有一个表达式,,可以省略{}和return,他会自动返回表达式的运行结果Funcint, bool fnName4 a a % 2 0;//如下代码和53代码等价Funcint, int, bool fnName5 (a, b) a b;int[] ints new int[] { 3, 4, 5, 6 };FindFirst(ints, FindEven);FindFirst(ints, v v % 2 0);}static bool FindEven(int value){return value % 2 0;}public static T FindFirstT(T[] Arrs, FuncT, bool fn){for (int i 0; i Arrs.Length; i){if (fn(Arrs[i]) true){return Arrs[i];}}//返回当前类型的默认值return default(T);}}
}
上期习题答案
创建一个用于存储某公司员工信息的类Employee并且可以通过索引来访问员工的姓名和年龄。提示使用字典 Employee employee new Employee();employee[22] fanfan; // 员工年龄22名字 fanfanemployee[22] luoluo; // 员工年龄22名字 luoluoemployee[23] Bob; 员工年龄23名字 Bobemployee[aa] 25;employee[Bob] 29; //修改Bob的年龄为29创建一个名为DictionaryWrapper的类它包装了一个Dictionary对象并提供了一个索引器允许我们通过键的部分名称来访问字典中的值。提示索引器可以接收多个参数 DictionaryWrapper dictionaryWrapper new DictionaryWrapper(); //设置字典中的键值对 dictionaryWrapper[dog] 狗; dictionaryWrapper[cat] 猫; dictionaryWrapper[elephant] 大象;dictionaryWrapper[dolphin] 海豚;// 输出字典中的值 Console.WriteLine(通过完整键访问:); Console.WriteLine(dog的值是dictionaryWrapper[dog]); // 狗 Console.WriteLine(cat的值是 dictionaryWrapper[cat]); // 猫 Console.WriteLine(elephant的值是 dictionaryWrapper[elephant]); // 大象 Console.WriteLine(dolphin的值是dictionaryWrapper[dolphin]); // 海豚Console.WriteLine(\n通过键的部分名称访问:);Console.WriteLine(以\do\开头的键的第一个值是 dictionaryWrapper[do, 0]); // 狗 Console.WriteLine(以\do\开头的键的第二个值是 dictionaryWrapper[do,1]); // 海豚参考答案(1,2答案在同一项目下)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace 上周作业
{internal class Program{static void Main(string[] args){Employee employee new Employee();//设置员工的姓名和年龄employee[22] fanfan; // 员工年龄22名字 fanfanemployee[22] luoluo; // 员工年龄22名字 luoluoemployee[23] Bob; 员工年龄23名字 Bobemployee[aa] 25;employee[Bob] 29; //修改Bob的年龄为29Console.WriteLine(employee[22]);Console.WriteLine(employee[Bob]);//------------------------------------------------------------DictionaryWrapper dictionaryWrapper new DictionaryWrapper();// 设置字典中的键值对dictionaryWrapper[dog] 狗;dictionaryWrapper[cat] 猫;dictionaryWrapper[elephant] 大象;dictionaryWrapper[dolphin] 海豚;// 输出字典中的值Console.WriteLine(通过完整键访问:);Console.WriteLine(dog的值是 dictionaryWrapper[dog]);// 狗Console.WriteLine(dog的值是{0}, dictionaryWrapper[dog]); // 狗Console.WriteLine(dog的值是{dictionaryWrapper[dog]});Console.WriteLine(cat的值是 dictionaryWrapper[cat]); // 猫Console.WriteLine(elephant的值是 dictionaryWrapper[elephant]); // 大象Console.WriteLine(dolphin的值是 dictionaryWrapper[dolphin]); // 海豚Console.WriteLine(\n通过键的部分名称访问:);Console.WriteLine(以\do\开头的键的第一个值是 dictionaryWrapper[do, 0]); // 狗Console.WriteLine(以\do\开头的键的第二个值是 dictionaryWrapper[do, 1]); // 海豚}}}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace 上周作业
{/// summary/// 字典的包装类/// /summaryinternal class DictionaryWrapper{//存储键值对Dictionarystring, string map new Dictionarystring, string();public string this[string englishName]{get map[englishName];set map[englishName] value;}/// summary/// 根据名字的开头进行查询/// /summary/// param namestarNamekey以什么开头/param/// param namenum要找第几个,从0开始/param/// returns/returnspublic string this[string starName,int num]{get{//1.定义一个数字,记录当前找到了第几个int nowCount 0;//2.遍历字典,查询对应的键值对中key 以starName开头的foreach (var item in map){//判断key是否以starName开头if (item.Key.StartsWith(starName)){//相同 判断当前找到的是否为低num个if (nowCountnum){//如果个数匹配,则返回当前查到的数据return item.Value;}else{//个数如果不匹配 则个数累加nowCount;}}}//如果没有找到返回nullreturn null;}}}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;namespace 上周作业
{/// summary/// 员工信息类/// /summaryinternal class Employee{//字典: 存储所有员工的信息Dictionaryint, string peoples new Dictionaryint,string();public string this[int index]{get {//根据key获取value//如果这个key存在,则返回对应key的值,否则返回nullreturn peoples.ContainsKey(index) ? peoples[index]:null;}set {//字典也可以进行[key]value的方式进行操作//如果字段中对应的key存在,则修改,不存在则添加peoples[index] value;//if (peoples.ContainsKey(index))//判断字典中是否存在指定的键//{// peoples[index] value;//如果存在则进行修改//}//else//{// peoples.Add(index, value);//如果不存在则进行添加//}}}public int this[string name]{get {//查询字典中满足条件的键值对,如果没有则返回默认值return peoples.FirstOrDefault(item item.Value name).Key;}set {//先判断是否有个人 叫name 如果有 则将他先删除if (peoples.ContainsValue(name)){//foreach (var item in peoples)//{// Console.WriteLine($当前的键{item.Key}当前的的值{item.Value});// //判断当前的将只对是否为我们需要找的键值对,// if (item.Value name)// {// //先移出之前的键值对// peoples.Remove(item.Key);// }//}// 查询对应的值相同的那个键值对的键//移除之前Ian那个键值对 int key this[name];peoples.Remove(key);}//添加新的键值对Console.WriteLine(valuevalue);Console.WriteLine(namename);peoples.Add(value, name);}}}
}
本期习题 模拟List MyList myList1 new MyList(); myList1.Add(1); myList1.Add(20); 自定义 ForEach FindIndex Find… 觉得本篇文章写的还不错可以点赞收藏关注。主页有21天速通C#教程欢迎订阅!!!