类型参数使得设计类和方法时,不必确定一个或多个具体参数,其的具体参数可延迟到客户代码中声明、实现。
这意味着使用泛型的类型参数T,写一个类MyList<T>,客户代码可以这样调用:MyList<int>, MyList<string>或 MyList<MyClass>。
这避免了运行时类型转换或装箱操作的代价和风险。
下面是普通的方法调用:
1 public static void ShowInt(int iValue) 2 { 5 Console.WriteLine(" ShowInt方法 展示{0},其类型为{1}", iValue, typeof(int));//,iValue.GetType()); 6 } 7 8 public static void ShowLong(long lValue) 9 { 10 Console.WriteLine(" ShowLong方法 展示{0},其类型为{1}", lValue, lValue.GetType()); 11 } 12 13 public static void ShowString(string sValue) 14 { 15 Console.WriteLine(" ShowString方法 展示{0},其类型为{1}", sValue, sValue.GetType()); 16 } 17 18 public static void ShowDateTime(DateTime dValue) 19 { 20 Console.WriteLine(" ShowDateTime方法 展示{0},其类型为{1}", dValue, dValue.GetType()); 21 }
这样,每次都需要根据不同的类别调用不同的方法,这是很不方便的。
/// <summary> /// 1 通过继承,子类拥有父类的一切属性和行为,任何父类出现的地方,子类都可以代替 /// 2 object 类型是一切类型的父类 /// </summary> /// <param name="oValue"></param> public static void ShowObject(object oValue) { Console.WriteLine(" ShowObject方法 展示{0},其类型为{1}", oValue, oValue.GetType()); }
这样,通过万类之母object,不论什么类型都可以调用,只需要一个方法,达到了代码的重用。
但是,需要装箱和拆箱操作,有效率上的损失,所以请看下面的方法:
1 public static void Show<T>(T tValue) 2 { 3 Console.WriteLine(" Show<T>方法 展示{0},其类型为{1}", tValue, tValue.GetType());4 }
通过泛型的延迟申明,可以将两者的不足之处相互结合,达到代码的重用。
所谓延迟申明,就是先不什么类型,用一个占位符代替,当要使用的时候再指定所需要的类型。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------泛型约束:
1 public static T Show<T>(T tValue) 2 //where T : class //引用类型 3 //where T : struct //值类型 4 { 5 Console.WriteLine(" Show<T>方法 展示{0},其类型为{1}", tValue, tValue.GetType());//,iValue.GetType());// 6 return default(T);//根据泛型类型,提供默认值 7 }logs_code_hide('9a935e1b-a7db-4312-894b-9bc8182a6e77',event)" src="/Upload/Images/2016092505/2B1B950FA3DF188F.gif" alt="" />
1 public class BaseModel 2 { 3 public int Id { get; set; } 4 public string TableName { get; set; } 5 } 6 7 public class People : BaseModel 8 { 9 public People() 10 { } 11 public string Name { get; set; } 12 public int Age { get; set; } 13 public string Sex { get; set; } 14 /// <summary> 15 /// 打招呼 16 /// </summary> 17 public string Hi { get; set; } 18 } 19 20 public interface ISports 21 { 22 void KickShuttlecock(); 23 } 24 25 public interface IWork 26 { 27 void DoJob(); 28 } 29 30 public class Chinese : People, ISports, IWork 31 { 32 public string Majiang { get; set; } 33 /// <summary> 34 /// 构造函数 35 /// </summary> 36 /// <param name="name"></param> 37 public Chinese(string name) 38 { 39 base.Hi = "早上好,吃了吗"; 40 base.TableName = "P_Chinese"; 41 } 42 public Chinese() 43 { 44 base.Hi = "早上好,吃了吗"; 45 base.TableName = "P_Chinese"; 46 } 47 48 49 public void KickShuttlecock() 50 { 51 Console.WriteLine("踢毽子"); 52 } 53 54 public void DoJob() 55 { 56 Console.WriteLine("养家糊口"); 57 } 58 }View Code
1 public static T Hi<T>(T t) where T : People, ISports, IWork, new() 2 { 3 T tModel = new T();//new()约束表明T拥有一个无参数的构造函数 4 tModel.Id = 11;//People约束决定 5 tModel.Name = "花心胡萝卜";//people约束决定 6 tModel.Sex = "男";//people约束决定 7 8 tModel.KickShuttlecock();//ISports接口约束决定 9 tModel.DoJob();//IWork接口约束决定 10 return tModel; 11 }
通过上面看出来,约束就是一种限定。只有符合约束类型的参数才能代替给定的类型参数。
比如下面的调用:
1 Chinese chinese = new Chinese() 2 { 3 Id = 123, 4 Name = "天忝♂开心" 5 }; 6 GenericConstraint.Hi<Chinese>(chinese);