点击返回 .net 初级高级 武林秘籍内功
大纲:
1.泛型的由来: CLR+JIT 延迟申明
2.泛型与object的对比、代码举例
3.泛型类、泛型方法、泛型接口、泛型委托
4.泛型约束
5.泛型的协变逆变
1.泛型的由来: CLR+JIT 延迟申明
泛型基本概念:.NET 泛型是一个很强大的新特性,它为每一种对象生成一份单独的代码(也就是所谓的“实例化”),这一份量身顶做的代码具有很高的效率,是强类型的,不需要运行期多态的支持和负担,有了泛型,就不再需要Object类来参与实现一些通用类或方法了.
泛型的作用: 在CLR(common language runtime)1.0中,当要创建一个灵活的类或方法,但该类或方法在编译期问不知道使用什么类,就必须以System.Object类为基础进行处理,而Object类在编译期间没有类型安全性,又必须进行强制类型转换.另外,给值类型使用Object类会有性能损失,这给程序开发带来诸多不便.故在CLR 2.0(.NET 3.5基于CLR 2.0)中,提供了泛型.
/// <summary> /// 打印个int值 /// </summary> /// <param name="iParameter"></param> public static void ShowInt(int iParameter) { Console.WriteLine("This is {0},parameter={1},type={2}", typeof(CommonMethod).Name, iParameter.GetType().Name, iParameter); } /// <summary> /// 打印个string值 /// </summary> /// <param name="sParameter"></param> public static void ShowString(string sParameter) { Console.WriteLine("This is {0},parameter={1},type={2}", typeof(CommonMethod).Name, sParameter.GetType().Name, sParameter); } /// <summary> /// 打印个DateTime值 /// </summary> /// <param name="oParameter"></param> public static void ShowDateTime(DateTime dtParameter) { Console.WriteLine("This is {0},parameter={1},type={2}", typeof(CommonMethod).Name, dtParameter.GetType().Name, dtParameter); } //如果做数据库查询,每一个实体对应的表,那岂不是每一个实体都要写一个方法吗? 看看调用: int iValue = 123; string sValue = "456"; DateTime dtValue = DateTime.Now; object oValue = "789"; ShowInt(iValue); ShowString(sValue); ShowDateTime(dtValue);
/// <summary> ///为什么用object 作为参数类型,调用的时候,可以把任何类型都传进来 /// ///C#: 任何父类出现的地方 都可以用子类代替; ///Object类型是一切类型的父类 /// ///Object 出现的都可以让任何类型传进来 /// /// 但是:有2个问题 /// 性能问题:会出现装箱和拆箱; /// 类型安全问题。 /// </summary> /// <param name="oParameter"></param> public static void ShowObject(object oParameter) { Console.WriteLine("This is {0},parameter={1},type={2}", typeof(CommonMethod), oParameter.GetType().Name, oParameter); } 看看调用: ShowInt(iValue); ShowString(sValue); ShowDateTime(dtValue);
/// <summary> /// 泛型方法:需要在方法名的后面带一个<>,需要定义T, T是什么呢? 不知道, /// T:类型参数,只是一个占位符,类型在声明其实不确定,在调用的时候,确定类型。 /// /// 延迟声明,推迟一切可以推迟的,事情能晚点做就晚点做。 /// 在使用的时候,需要指定明确的类型 /// 泛型方法性能和普通方法差不多,可以用一个方法满足多个类型的需求 /// 集成了前面2种的各自的长处。既可以安全调用,性能又好,并且可以用一个方法代替N个方法 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tParameter"></param> public static void Show<T>(T tParameter) { Console.WriteLine("This is {0},parameter={1},type={2}", typeof(CommonMethod), tParameter.GetType().Name, tParameter); } 看看调用: Show(iValue); //如果类型参数,可以通过参数类型推导出来,那么就可以省略 /* Show<int>(sValue);*/// 因为类型错了 Show(sValue); Show<DateTime>(dtValue); Show<object>(oValue);
3.泛型类、泛型方法、泛型接口、泛型委托
泛型方法 一个方法满足多个类型的需求
泛型类 就是一个类 满足多个类型的需求
泛型接口 就是一个接口 满足多个多个类型的需求
泛型委托 就是一个委托 满足多个多个类型的需求
a.泛型类:
//泛型类的定义在常规的类后面加<T>,T为占位符,可以任何字符代替。 //eg: public class Student<T>{} //亦可以多个类型。占位符不重复,用逗号隔开 //eg: public class People<T,A,B,C>{} //例子a: public class ClassA<T> { /// <summary> /// 获取T的类型全名称 /// </summary> /// <returns></returns> public string GetTTypeName() { return typeof(T).FullName; } } //使用 //使用泛型来打印实例类型 { ClassA<int> aInt = new ClassA<int>(); Console.WriteLine(aInt.GetTTypeName());//System.Int32 ClassA<string> aStr = new ClassA<string>(); Console.WriteLine(aStr.GetTTypeName());//System.String Console.ReadLine(); } //例子b: public class ClassB<T,A> where T:struct //约束T是个struct where A:class,new () //约束A是个引用类型,无参数构造函数约束 { /// <summary> /// 获取T的类型全名称 /// </summary> /// <returns></returns> public string GetTTypeName() { return typeof(T).FullName; } }
b.泛型方法:
例子在上面的2.“使用泛型”那有。
c.泛型接口:
//我们有4个类(人类、中国人、广东人、日本人), //中国人继承人类,广东人继承中国人。日本人没继承人类。 //有2个接口(IWork,ISports) public interface ISports { void Pingpang(); } public interface IWork { void Work(); } /// <summary> /// 人类 /// 基本属性有:ID,名称,会说Hi /// </summary> public class People { public int Id { get; set; } public string Name { get; set; } public void Hi() { } } /// <summary> /// 中国人:继承了人类(拥有人类的基本属性) /// 也有自己的说Hi方式,有额外的属性,还实现了运动,工作 /// </summary> public class Chinese : People, ISports, IWork { public void Tradition() { Console.WriteLine("仁义礼智信,温良恭俭让"); } public void SayHi() { Console.WriteLine("吃了么?"); } public void Pingpang() { Console.WriteLine("打乒乓球..."); } public void Work() { Console.WriteLine("工作中..."); } } /// <summary> /// 广东人:继承了中国人(拥有中国人的基本属性) /// 额外还会吃。 /// </summary> public class GuangDong : Chinese { public void Eat() { Console.WriteLine("正在吃福建人..."); } } /// <summary> /// 日本人:只实现了运动 /// </summary> public class Japanese : ISports { public int Id { get; set; } public string Name { get; set; } public void Pingpang() { Console.WriteLine("雅美蝶,打乒乓球..."); } } //如下调用 People people = new People() { Id = 1, Name = "令狐冲" }; Chinese chinese = new Chinese() { Id = 2, Name = "岳不群" }; GuangDong guangDong = new GuangDong() { Id = 3, Name = "小林子" }; Japanese japanese = new Japanese() { Id = 4, Name = "冲田杏梨" }; //现在有这4个对象 //我想要他们,统统运动起来,如下: //常规: // people 没有运动的方法 chinese.Pingpang(); guangDong.Pingpang(); japanese.Pingpang(); //如果,我想他们统统运动起来,使用把对象传入进去的方法, //那么又回到上面我说,替这3个类加3个方法 /*eg: * public static void ChineseShowSports(Chinese chinese){ chinese.Pingpang(); } * public static void GuangDongShowSports(GuangDong guangDong){guangDong.Pingpang(); } * public static void JapaneseShowSports(Japanese japanese){japanese.Pingpang(); } */ //调用如下 ChineseShowSports(chinese); GuangDongShowSports(guangDong); JapaneseShowSports(japanese); //这样也是可以的,那么下面的泛型就可以把他们泛型成一个方法 /*eg: * public static void ShowSports<T>(T t) where T: People,ISports * { * t.Pingpang(); * } */ //调用如下 ShowSports(chinese); ShowSports(guangDong); ShowSports(japanese);
从这俩张图可见,where T 起到了约束,所以可以使用里面的方法和属性。
4.泛型约束
在上面的代码中,可以看到一些泛型约束的使用了。
泛型约束 是 在泛型类、方法、等对其调用的约束,起到保护作用和使用(履行义务+享受权利),使用方法是 后面跟 where T : Class,new()等。多重约束使用逗号隔开。
多泛型如T,G,F,使用多个where。如:
public static void ShowSports<T,G,F>(T t) where T :People,ISports where G:ISports where F:Class { //这里是业务,可以使用 T,G,F }
说明
where T:People// 约束T是People类型
where T:ISports// 约束T是实现ISports类型
where T :Class// 约束T是引用类型
where T :new()// 无参数构造的函数约束
where T :struct// 约束T是结构类型
举个例子
我要这3个对象运动一下,要求是个人才能运动
public static void ShowSportsByPeople<T>(T t) where T :People, ISports { t.Pingpang(); } //调用 ShowSportsByPeople(chinese);//打乒乓球... ShowSportsByPeople(guangDong);//打乒乓球... ShowSportsByPeople(japanese);//这个会报错,老师亚麻跌不出来 //说明泛型约束,保证了调用安全。
5.泛型的协变逆变
选修:in 和 out
哈哈,不说了
点击返回 .net 初级高级 武林秘籍内功