大家一起学泛型(一)
从简单的例子开始
有一天恒锐召开运动会,技术部要出两个跳高运动员,经理对我说,在小姜和孙晰锐中间选一个吧,你写一个方法,选出他们中最高那个参加。于是我写了如下代码:
跳高运动员实体类
public class Jumper
{
// 姓名
private string mName;
// 身高
private int mHeight;
public string Name {
get { return this.mName; }
}
public int Height {
get { return this.mHeight; }
}
public Jumper( string name, int height) {
this.mName = name;
this.mHeight = height;
}
}
{
// 姓名
private string mName;
// 身高
private int mHeight;
public string Name {
get { return this.mName; }
}
public int Height {
get { return this.mHeight; }
}
public Jumper( string name, int height) {
this.mName = name;
this.mHeight = height;
}
}
选拔方法
public Jumper WhoIsHigher(Jumper jumper1, Jumper jumper2)
{
if (jumper1.Height > jumper2.Height)
{
return jumper1;
}
else
{
return jumper2;
}
}
{
if (jumper1.Height > jumper2.Height)
{
return jumper1;
}
else
{
return jumper2;
}
}
过了几天,增加了体育项目,技术部要出两个举重运动员,经理对我说,在于泽龙和刘志允中间选一个吧,你写一个方法,选出他们中最重的那个参加。于是我又写了如下代码:
举重运动员实体类
public class WeightLifter
{
// 姓名
private string mName;
// 体重
private int mWeight;
public string Name {
get { return this.mName; }
}
public int Weight {
get { return this.mWeight; }
}
public WeightLifter( string name, int weight) {
this.mName = name;
this.mWeight = height;
}
}
{
// 姓名
private string mName;
// 体重
private int mWeight;
public string Name {
get { return this.mName; }
}
public int Weight {
get { return this.mWeight; }
}
public WeightLifter( string name, int weight) {
this.mName = name;
this.mWeight = height;
}
}
选拔方法
public WeightLifter WhoIsWeighter(WeightLifter Lifter1, WeightLifter Lifter2)
{
if (Lifter1.Weight > Lifter2.Weight)
{
return Lifter1;
}
else
{
return Lifter2;
}
}
{
if (Lifter1.Weight > Lifter2.Weight)
{
return Lifter1;
}
else
{
return Lifter2;
}
}
过了几天,又增加了许多体育项目,经理让我根据不同条件选拔选手,比如根据力量最大,步伐最大......然后我崩溃了...
改进的方法
public object WhoIsBetter(object obj1, object obj2)
{
object result = obj2;
switch (obj1.GetType().ToString())
{
case "Generic.Jumper":
if (((Jumper)obj1).Height > ((Jumper)obj2).Height)
{
result=obj1;
}
break;
case "Generic.WeightLifter":
if (((WeightLifter)obj1).Weight > ((WeightLifter)obj2).Weight)
{
result=obj1;
}
break;
case "System.Int32":
if (((System.Int32)obj1).CompareTo(obj2) > 0)
{
result=obj1;
}
break;
}
return result;
}
{
object result = obj2;
switch (obj1.GetType().ToString())
{
case "Generic.Jumper":
if (((Jumper)obj1).Height > ((Jumper)obj2).Height)
{
result=obj1;
}
break;
case "Generic.WeightLifter":
if (((WeightLifter)obj1).Weight > ((WeightLifter)obj2).Weight)
{
result=obj1;
}
break;
case "System.Int32":
if (((System.Int32)obj1).CompareTo(obj2) > 0)
{
result=obj1;
}
break;
}
return result;
}
弱点1:方法的重用性
假设我们要让WhoIsBetter方法支持更多类型,支持以后提出的新需求,那么就要不断扩展方法的内部代码,增加了维护成本。
弱点2:类型安全问题
如果上面的代码我把跳高运动员和举重运动员比较,就会出现异常。
弱点3:装箱拆箱导致的性能问题
if (((System.Int32)obj1).CompareTo(obj2) > 0 )
当向WhoIsBetter方法中传递int参数时,object转换为int导致了拆箱操作:
泛型出马,一个顶俩
泛型的解决方案
public class Compare<T>
{
public T WhoIsBetter(T t1, T t2)
{
if (t1.CompareTo(t2) > 0)
{
return t1;
}
else
{
return t2;
}
}
}
{
public T WhoIsBetter(T t1, T t2)
{
if (t1.CompareTo(t2) > 0)
{
return t1;
}
else
{
return t2;
}
}
}
泛型引用
Jumper jumper1 = new Jumper( "小姜" , 160 );
Jumper jumper2 = new Jumper( "孙晰锐" , 180 );
WeightLifter lifter1 = new WeightLifter( "于泽龙" , 120 );
WeightLifter lifter2 = new WeightLifter( "刘志允" , 180 );
Console.WriteLine(( new Compare<Jumper>().WhoIsBetter(jumper1, jumper2)).Name);
Console.WriteLine(( new Compare<WeightLifter>().WhoIsBetter(lifter1, lifter2)).Name);
Jumper jumper2 = new Jumper( "孙晰锐" , 180 );
WeightLifter lifter1 = new WeightLifter( "于泽龙" , 120 );
WeightLifter lifter2 = new WeightLifter( "刘志允" , 180 );
Console.WriteLine(( new Compare<Jumper>().WhoIsBetter(jumper1, jumper2)).Name);
Console.WriteLine(( new Compare<WeightLifter>().WhoIsBetter(lifter1, lifter2)).Name);
泛型与非泛型比较
非泛型 | 泛型 | |
代码的简洁程度 | 如果参数类型过多的话,更繁琐 | 如果参数类型过多的话,更简洁 |
性能 | 当涉及到大量的装箱和拆箱操作时,性能较差 | 当涉及到大量的装箱和拆箱操作时,性能较优 |
编写的难易程度 | 易于编写,参数类型更具体 | 比较难编写,因为它更抽象 |
维护的难易程度 | 类型增加时需要不断的增加编码 | 易于维护 |
泛型约束
在泛型类型定义中,where 子句用于指定对下列类型的约束:这些类型可用作泛型声明中定义的类型参数的实参。
public class Compare<T> where T : IComparable
where T : IComparable ,这段代码表示对T的类型约束,表示参数T必须实现了IComparable接口(定义一种特定于类型的通用比较方法,值类型或类通过实现此方法对其实例进行排序)。