Console.WriteLine(((Boy)new Compare().WhoIsBetter(boy1, boy2)).Name);
Console.WriteLine(((Girl)new Compare().WhoIsBetter(girl1, girl2)).Name);
Console.WriteLine(new Compare().WhoIsBetter(boy1.Height, boy2.Height));
Console.WriteLine(new Compare().WhoIsBetter(girl1.Weight, girl2.Weight));
Console.ReadLine();
}
测试结果:
刘德华
周迅
175
120
OK,截止目前,似乎比较完美了,男演员比身高,女演员比体重,还支持int类型比大小,WhoIsBetter方法具有了重用性,如果有需要,往后还能扩展,拿来比较任意两个对象。在泛型出现以前,似乎确实比较完美,但这也只是相对的,我们来看看目前代码的弱点:
弱点1:方法的重用性
假设我们要让WhoIsBetter方法支持更多类型,比如支持基本的double,char,bool类型,支持以后导演可能提出的配角比较,群众比较,那么就必须不断的扩展方法内部代码,这带来极大的维护成本。
弱点2:类型安全问题
复制代码 代码如下:
//测试
static void Main(string[] args)
{
Boy boy1 = new Boy("潘长江", 165);
Boy boy2 = new Boy("刘德华", 175);
Girl girl1 = new Girl("巩俐", 120);
Girl girl2 = new Girl("周迅", 80);
Console.WriteLine(((Boy)new Compare().WhoIsBetter(boy1, girl1)).Name);
Console.ReadLine();
}
如上代码我拿潘长江跟巩俐去比较。虽然万能的object给我们带来了便捷,同时也带来了风险,这段代码编译完全可以通过,但运行时会出现异常,girl对象是没法转换为Boy类型的,现实里去韩国可以变性,但代码里绝对不行。所以这个方法就像颗定时炸弹,一不小心传错了参数,就会导致严重后果,并且编译阶段完全不被发现。
弱点3:装箱拆箱导致的性能问题
当向WhoIsBetter方法中传递int参数时,object转换为int导致了拆箱操作:
if (((System.Int32)obj1).CompareTo(obj2) > 0)
反编译获取MSIL:
IL_0093: unbox.any [mscorlib]System.Int32
C#是强类型语言,但只要引用类型与值类型的相互转换,就避免不了Box与Unbox。有关装箱与拆箱的知识请读者自行查阅相关资料,此处不作详述。
理解泛型
OK,到泛型登场了,摘录了一段MSDN中对泛型的描述:泛型类和泛型方法同时具备可重用性、类型安全和效率,这是非泛型类和非泛型方法无法具备的。这三点,跟我们上面的例子相吻合。
看看使用泛型的解决方案:
复制代码 代码如下:
public class Compare<T> where T : IComparable
{
public T WhoIsBetter(T t1, T t2)
{
if (t1.CompareTo(t2) > 0)
{
return t1;
}
else
{
return t2;
}
}
}
//测试
static void Main(string[] args)
{
Boy boy1 = new Boy("潘长江", 165);
Boy boy2 = new Boy("刘德华", 175);
Girl girl1 = new Girl("巩俐", 120);
Girl girl2 = new Girl("周迅", 80);