上文博文《浅谈泛型(一)》中简单总结了泛型的安全性和高效性,接下来说一下泛型的可复用性。
可复用性,我们对这个词已经再熟悉不过了,简单地说就是对重复代码进行抽象和封装后达到的效果。那么在泛型中是怎样体现的呢?
假设现在我想检测键盘的某一个数字键是否可用
public class MyTest
{
public void intTest(int a)
{
Console.writeline(a);
}
}
检测完数字键,我又想检测看看字母键是否可用,这时需要添加方法
public class MyTest
{
//定义的检测方法
public void intTest(int a)
{
Console.writeline(a);
}
public void strTest(string p)
{
Console.writeline(p);
}
}
//调用过程
MyTest mytest=new MyTest ();
mytest.intTest(1);
mytest.strTest('a');
如果我还想继续检测'.'键是否可用,那么还得再次重新写一个类似的关于double或float类型的检测方法。
“代码复制是最愚蠢、最低效的无用功”,仔细观察可以发现他们的共同点:除了输入的类型不同,其余都一样,这时候我们就可以考虑使用泛型了。泛型把类或方法的类型的确定推迟到实例化该类或方法的时候,这样大大提交了代码的复用性。
。
public class MyTest<T>
{
public void test(T t){
Console.writeline(t);
}
}
//调用过程
MyTest<int> inttest=new MyTest<int>();
intest.test(1);
MyTest<string> strtest=new MyTest<string>();
strTest.test('a');
尽管现在MyTest类确实可以完成所需要的工作,但是这样一来即使不使用test()方法在创建MyTest类的实例时也必须传递一个类型参数给它。因此为了解决这个问题,我们可以考虑将类型参数加到具体方法上,即泛型方法。
public class MyTest
{
public void test<T>(T t){
Console.writeline(t);
}
}
MyTest mytest=new MyTest ();
mytest.test<int>(1);
mytest.test<string>('a');
mytest.test<float>(1.0);
有的时候使用泛型,需要用where对类型参数作出限定即泛型约束。有以下几种方式:
Where T:struct 限制类型参数T必须为值类型
Where T:class 限制类型参数T必须是引用类型
Where T:new() 限制类型参数T必须有一个缺省的构造函数
Where T:NameOfClass 限制类型参数必须继承自某个类或实现某个接口
应用范例:
public class model<T> where T:struct
{
..............
}
//调用过程
model<int> model1=new model<int>;
model<float> model2=new model<float>;
public class model<T> where T:class
{
..............
}
public class Dog{}
public class Cat{}
//调用过程
model<Dog> model1=new model<Dog>;
model<Cat> model2=new model<Cat>;
public class model<T> where T:IComparable,new()
{
//注意:当有多个限制时,new()放在最后
..............
}
泛型不仅仅应用在输入参数,返回值类型同样适用。这里简单给出一个小例子作为参考。
public static T GetObj<T>(Employee model)
{
T result = default(T);
if (model is T)
{
result = (T)(object)model; //或 (T)((object)model);
}
return result;
}
通过这两篇博文的总结,泛型的优点已经很明显了,不仅性能高、安全性强,而且可复用性也得到了充分利用。这些都需要通过实践去细细体会,更多的惊喜等待慢慢去挖掘。