C# 泛型,泛型约束
泛型主要是为了解决代码的复用性
在泛型出现之前,如果需要用到不同的参数类型,但是方法体一样的时候,需要定义多个不同类型参数的方法,这样有太多的重复代码如下
public static void ShowInt(int iParameter) { Console.WriteLine("类名称:"+typeof(TestFunctionClass).FullName+",参数类型:"+ iParameter.GetType().ToString() + ",参数Value:"+iParameter); } public static void ShowString(string sParameter) { Console.WriteLine("类名称:" + typeof(TestFunctionClass).FullName + ",参数类型:" + sParameter.GetType().ToString() + ",参数Value:" + sParameter); } public static void ShowDate(DateTime dParameter) { Console.WriteLine("类名称:" + typeof(TestFunctionClass).FullName + ",参数类型:" + dParameter.GetType().ToString() + ",参数Value:" + dParameter); }
在Main方法中进行调用
Console.WriteLine("最开始展示不同类型参数的信息的时候,需要定义多个不同类型的方法,而方法内容是几乎一样的"); TestFunctionClass.ShowInt(1); TestFunctionClass.ShowString("aaa"); TestFunctionClass.ShowDate(DateTime.Now); Console.ReadLine();
输出结果
后来发现使用里氏替换原则,任何使用父类的地方可以使用子类来进行替换,于是有了下面这种写法(object是任何子类的父类)
public static void ShowObject(object oParameter) { Console.WriteLine("类名称:" + typeof(TestFunctionClass).FullName + ",参数类型:" + oParameter.GetType().ToString() + ",参数Value:" + oParameter); }
在主方法中可以直接传递
Console.WriteLine("后来发现通过里氏替换原则,任何父类出现的地方可以用子类来进行替换,可以节省大部分代码"); TestFunctionClass.ShowObject(2); TestFunctionClass.ShowObject("bbb"); TestFunctionClass.ShowObject(DateTime.Now); Console.WriteLine("但是这样出现一个问题,出现类类型之间的转换,发生了装箱操作,这样使性能得到了非常大的损耗,(值类型转换为引用类型)");
输出结果
这个时候出现了泛型,泛型是在定义的时候,不直接声明类型,直到调用的时候再去指定,延时声明的作用,避免了装箱操作,减少了性能损耗
public static void ShowFanXing<T>(T tParameter) { Console.WriteLine("类名称:" + typeof(TestFunctionClass).FullName + ",参数类型:" + tParameter.GetType().ToString() + ",参数Value:" + tParameter); }
在主方法中调用
TestFunctionClass.ShowFanXing<int>(3); TestFunctionClass.ShowFanXing<string>("ccc"); TestFunctionClass.ShowFanXing<DateTime>(DateTime.Now); Console.WriteLine("使用泛型的时候性能和使用普通方法类似,远大于通过object(里氏替换原则)的性能(前提:如果发生了装箱操作的时候");
输出结果
这个时候,泛型的定义知道了,但是咱们发现好像泛型没有什么意义,在方法内只能使用的还是基类的一些属性和方法
这个时候需要引入一个东西,泛型约束,通过泛型约束,咱们可以在泛型方法(泛型类)中使用约束的属性和方法
先声明一些基础类
public class Pepple { public int Age { get; set; } public string Name { get; set; } public string SayHi() { return "Hi,My Name is" + Name + ",My Age Is " + Age; } } public class Chinese : Pepple, ISiChuan { public string Dialect { get; set; } public string Food() { return "火锅"; } } public class Japanese : Pepple, IGuangDao { public string ViewSakura() { return "美しい桜"; } } public interface ISiChuan { string Dialect { get; set; } string Food(); } public interface IGuangDao { string ViewSakura(); }
泛型约束,方法
public static void ShowPeople<T>(T tParameter) where T : Pepple { Console.WriteLine("名字:" + tParameter.Name + ",年龄:" + tParameter.Age); Console.WriteLine("说话:" + tParameter.SayHi()); }
在主方法中可以进行调用
Pepple people = new Pepple() { Age = 1, Name = "People Name" }; //里氏替换原则 Pepple chinese = new Chinese() { Age = 1, Name = "张三" }; TestFunctionClass.ShowPeople<Pepple>(people); TestFunctionClass.ShowPeople<Pepple>(chinese); Console.WriteLine("这个时候还有一个问题,虽然用了泛型约束,可以使用约束类的属性和方法,但是,子类的一些特性还是不能访问,这个时候出现了接口约束"); Console.ReadLine();
输出结果
泛型接口约束
public static void ShowPeopleDetail<T>(T tParameter) where T : Pepple, ISiChuan { Console.WriteLine("名字:" + tParameter.Name + ",年龄:" + tParameter.Age); Console.WriteLine("说话:" + tParameter.SayHi()); Console.WriteLine("喜欢吃:" + tParameter.Food()); }
执行结果
结束