在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本笔记摘抄自:https://www.cnblogs.com/dotnet261010/p/9034594.html,记录一下学习过程以备后续查用。 一、什么是泛型泛型是C#2.0推出的新语法,不是语法糖,而是2.0由框架升级提供的功能。泛型类就类似于一个模板,可以在需要时为这个模板传入任何我们需要的类型。 二、为什么使用泛型下面代码演示输出几种类型的相关信息: class Program { /// <summary> /// 打印帮助类 /// </summary> public class ShowHelper { /// <summary> /// ShowInt /// </summary> /// <param name="intParam"></param> public static void ShowInt(int intParam) { Console.WriteLine($"Class={typeof(ShowHelper).Name},Type={intParam.GetType().Name},Parameter={intParam}"); } /// <summary> /// ShowString /// </summary> /// <param name="strParam"></param> public static void ShowString(string strParam) { Console.WriteLine($"Class={typeof(ShowHelper).Name},Type={strParam.GetType().Name},Parameter={strParam}"); } /// <summary> /// ShowDateTime /// </summary> /// <param name="dtParam"></param> public static void ShowDateTime(DateTime dtParam) { Console.WriteLine($"Class={typeof(ShowHelper).Name},Type={dtParam.GetType().Name},Parameter={dtParam}"); } } static void Main(string[] args) { #region 非泛型打印方式一 ShowHelper.ShowInt(123); ShowHelper.ShowString("Hello World."); ShowHelper.ShowDateTime(DateTime.Now); Console.Read(); #endregion } } 运行结果如下: 上面3个方法很相似,除了参数类型不同外,实现的功能是一样的,可以稍作优化。 下面代码演示使用继承的方式输出几种类型的相关信息: class Program { /// <summary> /// 打印帮助类 /// </summary> public class ShowHelper { /// <summary> /// ShowType /// </summary> /// <param name="obj"></param> public static void ShowType(object obj) { Console.WriteLine($"Class={typeof(ShowHelper).Name},Type={obj.GetType().Name},Parameter={obj}"); } } static void Main(string[] args) { #region 非泛型打印方式二 ShowHelper.ShowType(123); ShowHelper.ShowType("Hello World."); ShowHelper.ShowType(DateTime.Now); Console.Read(); #endregion } } 功能实现没有问题,只是object与其它类型的转换,涉及到装箱和拆箱的过程,这个是会损耗程序的性能的。 三、泛型类型参数在泛型类型或方法的定义中,泛型类型参数可认为是特定类型的占位符。 下面代码演示使用泛型的方式输出几种类型的相关信息: class Program { /// <summary> /// 打印帮助类 /// </summary> public class ShowHelper { /// <summary> /// Show /// </summary> /// <param name="obj"></param> public static void Show<T>(T tParam) { Console.WriteLine($"Class={typeof(ShowHelper).Name},Type={tParam.GetType().Name},Parameter={tParam}"); } } static void Main(string[] args) { #region 泛型打印方式 ShowHelper.Show(123); ShowHelper.Show("Hello World."); ShowHelper.Show(DateTime.Now); Console.Read(); #endregion } } 运行结果如下: 1、为什么泛型可以解决上面的问题呢? 泛型是延迟声明的:即定义的时候没有指定具体的参数类型,把参数类型的声明推迟到调用的时候才给它指定。 2、泛型究竟是如何工作的呢? 程序执行原理:控制台程序最终会编译成一个exe程序。当exe被点击的时候,会经过JIT(即时编译器)的编译,最终生成二进制代码才能被计算机执行。 泛型工作原理:泛型加入到语法以后,VS自带的编译器做了升级,升级之后编译时若遇到泛型,会做特殊的处理:生成占位符。然后经过JIT编译的时候,会把上面编译生成的占位符替换成具体的数据类型。 下面代码演示泛型占位符: class Program { static void Main(string[] args) { #region 泛型占位符 Console.WriteLine(typeof(List<>)); Console.WriteLine(typeof(Dictionary<,>)); Console.Read(); #endregion } } 运行结果如下: 3、泛型性能问题 下面代码演示泛型性能测试: class Program { static void Main(string[] args) { #region 泛型性能测试 long commonTime = 0; long objectTime = 0; long genericTime = 0; Stopwatch watch = new Stopwatch(); watch.Start(); for (int i = 0; i < 10000; i++) { ShowHelper.ShowInt(123); } watch.Stop(); commonTime = watch.ElapsedMilliseconds; watch.Reset(); watch.Start(); for (int i = 0; i < 10000; i++) { ShowHelper.ShowType(123); } watch.Stop(); objectTime = watch.ElapsedMilliseconds; watch.Reset(); watch.Start(); for (int i = 0; i < 10000; i++) { ShowHelper.Show(123); } watch.Stop(); genericTime = watch.ElapsedMilliseconds; Console.Clear(); Console.WriteLine($"Common time={commonTime}ms"); Console.WriteLine($"Object time={objectTime}ms"); Console.WriteLine($"Generic time={genericTime}ms"); Console.Read(); #endregion } } 运行结果如下: 从结果可以看出,泛型的性能是最高的。 四、泛型类下面代码演示泛型类: class Program { /// <summary> /// 泛型类 /// </summary> /// <typeparam name="T"></typeparam> public class GenericClass<T> { public T varT; } static void Main(string[] args) { #region 泛型类 //T是int类型 GenericClass<int> genericInt = new GenericClass<int> { varT = 123 }; Console.WriteLine($"The value of T={genericInt.varT}"); //T是string类型 GenericClass<string> genericString = new GenericClass<string> { varT = "123" }; Console.WriteLine($"The value of T={genericString.varT}"); Console.Read(); #endregion } } 运行结果如下: 五、泛型接口注:泛型在声明的时候可以不指定具体的类型,继承的时候也可以不指定具体类型,但是在使用的时候必须指定具体类型。 下面代码演示泛型接口: class Program { /// <summary> /// 泛型接口 /// </summary> public interface IGenericInterface<T> { T GetT(T t); } /// <summary> /// 泛型接口实现类 /// </summary> /// <param name="args"></param> public class GenericGet<T> : IGenericInterface<T> { T varT; public T GetT(T t) { varT = t; return varT; } } static void Main(string[] args) { #region 泛型接口 IGenericInterface<int> genericInterface = new GenericGet<int>(); var result = genericInterface.GetT(123); Console.WriteLine($"Result={result}"); Console.Read(); #endregion } } 运行结果如下: 六、泛型委托下面代码演示泛型委托: class Program { /// <summary> /// 泛型委托 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="t"></param> public delegate void SayHi<T>(T t); static void Main(string[] args) { #region 泛型委托 SayHi<string> sayHi = SayHello; sayHi("Hello World"); Console.Read(); #endregion } /// <summary> /// SayHello /// </summary> /// <param name="greeting"></param> public static void SayHello(string greeting) { Console.WriteLine($"{greeting}"); } } 运行结果如下: 七、泛型约束泛型约束,实际上就是约束的类型T,使T必须遵循一定的规则。比如T必须继承自某个类或者T必须实现某个接口等等。 怎样给泛型指定约束?其实也很简单,只需要where关键字,加上约束的条件。 泛型约束总共有五种:
7.1基类约束 下面代码演示基类约束: /// <summary> /// 运动类接口 /// </summary> public interface ISports { void Pingpong(); } /// <summary> /// 人类基类 /// </summary> public class People { public string Name { get; set; } public virtual void Greeting() { Console.WriteLine("Hello World."); } } /// <summary> /// 中国人 /// </summary> public class Chinese : People, ISports { public void FineTradition() { Console.WriteLine("自古以来,中华民族就保持着勤劳的优良传统。"); } public override void Greeting() { Console.WriteLine("吃饭了没?"); } public void Pingpong() { Console.WriteLine("乒乓球是中国的国球。"); } } static void Main(string[] args) { #region 泛型约束:基类约束 Chinese chinese = new Chinese() { Name = "中国人" }; ShowPeople(chinese); Console.Read(); #endregion } /// <summary> /// 基类约束 /// </summary> /// <param name="obj"></param> public static void ShowPeople<T>(T tParam) where T:People { Console.WriteLine($"{((People)tParam).Name}"); } } 运行结果如下: 注:基类约束时,基类不能是密封类,即不能是sealed类。sealed类表示该类不能被继承,在这里用作约束就无任何意义了,因为sealed类没有子类。 7.2接口约束 下面代码演示接口约束: class Program { /// <summary> /// 运动类接口 /// </summary> public interface ISports { void Pingpong(); } /// <summary> /// 人类基类 /// </summary> public class People { public string Name { get; set; } public virtual void Greeting() { Console.WriteLine("Hello World."); } } /// <summary> /// 中国人 /// </summary> public class Chinese : People, ISports { public void FineTradition() { Console.WriteLine("自古以来,中华民族就保持着勤劳的优良传统。"); } public override void Greeting() { Console.WriteLine("吃饭了没?"); } public void Pingpong() { Console.WriteLine("乒乓球是中国的国球。"); } } static void Main(string[] args) { #region 泛型约束:接口约束 Chinese chinese = new Chinese() { Name = "中国人" }; GetSportsByInterface(chinese); Console.Read(); #endregion } /// <summary> /// 接口约束 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="t"></param> /// <returns></returns> public static T GetSportsByInterface<T>(T t) where T : ISports { t.Pingpong(); return t; } } 运行结果如下: 7.3引用类型约束 class 引用类型约束保证T一定是引用类型的。 下面代码演示引用类型约束: class Program { /// <summary> /// 运动类接口 /// </summary> public interface ISports { void Pingpong(); } /// <summary> /// 人类基类 /// </summary> public class People { public string Name { get; set; } public virtual void Greeting() { Console.WriteLine("Hello World."); } } /// <summary> /// 中国人 /// </summary> public class Chinese : People, ISports { public void FineTradition() { Console.WriteLine("自古以来,中华民族就保持着勤劳的优良传统。"); } public override void Greeting() { Console.WriteLine("吃饭了没?"); } public void Pingpong() { Console.WriteLine("乒乓球是中国的国球。"); } } static void Main(string[] args) { #region 泛型约束:引用类型约束 Chinese chinese = new Chinese() { Name = "中国人" }; GetSportsByClass(chinese); Console.Read(); #endregion } /// <summary> /// 引用类型约束 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="t"></param> /// <returns></returns> public static T GetSportsByClass<T>(T t) where T : class { if (t is ISports) { (t as ISports).Pingpong(); } return t; } } 运行结果如下: 7.4值类型约束 struct 值类型约束保证T一定是值类型的。 下面代码演示值类型约束: class Program { /// <summary> /// 绩效工资 /// </summary> public struct Achievement { public double MeritPay { get; set; } public string Level { get; set; } public double ReallyPay() { switch (Level) { case "A": MeritPay = MeritPay * 1.0; break; case "B": MeritPay = MeritPay * 0.8; break; case "C": MeritPay = MeritPay * 0.6; break; case "D": MeritPay = 0; break; default: MeritPay = 0; break; }; return MeritPay; } } static void Main(string[] args) { #region 泛型约束:值类型约束 Achievement achievement = new Achievement { MeritPay = 500, Level = "B" }; var result = GetReallyPay(achievement).ReallyPay(); Console.WriteLine($"ReallyPay={result}"); Console.Read(); #endregion } /// <summary> /// 值类型约束 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="t"></param> /// <returns></returns> public static T GetReallyPay<T>(T t) where T : struct { return t; } } 运行结果如下: 7.5无参数构造函数约束 new() 下面代码演示无参数构造函数约束: class Program { /// <summary> /// 运动类接口 /// </summary> public interface ISports { void Pingpong(); } /// <summary> /// 人类基类 /// </summary> public class People { public string Name { get; set; } public virtual void Greeting() { Console.WriteLine("Hello World."); } } /// <summary> /// 中国人 /// </summary> public class Chinese : People, ISports { public void FineTradition() { Console.WriteLine("自古以来,中华民族就保持着勤劳的优良传统。"); } public override void Greeting() { Console.WriteLine("吃饭了没?"); } public void Pingpong() { Console.WriteLine("乒乓球是中国的国球。"); } } /// <summary> /// 广东人 /// </summary> public class Guangdong : Chinese { public Guangdong() { } public string Dialect { get; set; } public void Mahjong() { Console.WriteLine("这麻将上瘾的时候,一个人也说是三缺一呀。"); } } static void Main(string[] args) { #region 泛型约束:无参数构造函数约束 Guangdong guangdong = new Guangdong() { Name = "广东人" }; GetMahjong(guangdong); Console.Read(); #endregion } /// <summary> /// 无参数构造函数约束 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="t"></param> /// <returns></returns> public static T GetMahjong<T>(T t) where T : People, ISports, new() { if (t is |
请发表评论