泛型是c#2.0引入的一个新的特性,这个新的特性让人激动,由于泛型可以让程序更加简洁,更加安全,更加灵活,更加方便。那么什么是泛型,为什么它具有如此大的功能呢?还是从传统的程序设计开始说起。
10.4.1泛型的引入
现在实现一个交换两个变量的功能,这个函数名为Change。现在看一下具体的实现。例子Change的代码
namespace Change
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
int a = 3;
int b = 8;
Console.WriteLine("交换前:{0}<--->{1}", a, b);
p.Change(ref a, ref b);
Console.WriteLine("交换后:{0}<--->{1}", a, b);
Console.ReadKey();
}
//交换两个整型数
void Change(ref int a, ref int b)
{
int temp;
temp = a;
a = b;
b = temp;
}
}
}
程序运行的没有任何问题,现在又有了新的要求,需要交换两个char类型数据的大小。因为c#中允许重载,所以能够在原先的代码中继续添加函数char Change(ref char a,ref char b),如果又有新的要求,要求交换两个双精度数据,继续添加double Change(ref double a,ref double b),于是完整的代码是
namespace Change
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
int a = 3;
int b = 8;
Console.WriteLine("交换前:{0}<--->{1}", a, b);
p.Change(ref a, ref b);
Console.WriteLine("交换后:{0}<--->{1}", a, b);
char c1 = 'a';
char c2 = 'd';
Console.WriteLine("交换前:{0}<--->{1}", c1, c2);
p.Change(ref c1, ref c2);
Console.WriteLine("交换后:{0}<--->{1}", c1, c2);
double d1 = 34.6;
double d2 = 86.4;
Console.WriteLine("交换前:{0}<--->{1}", d1, d2);
p.Change(ref d1, ref d2);
Console.WriteLine("交换后:{0}<--->{1}", d1, d2);
Console.ReadKey();
}
//交换两个整型数
void Change(ref int a, ref int b)
{
int temp;
temp = a;
a = b;
b = temp;
}
//交换两个字符
void Change(ref char a, ref char b)
{
char temp;
temp = a;
a = b;
b = temp;
}
//交换双精度数据
void Change(ref double a, ref double b)
{
double temp;
temp = a;
a = b;
b = temp;
}
}
}
在编写代码过程中,你不停的复制,粘贴,不停的变换类型名。可是在这个过程当中你会逐渐发现这个函数的功能基本一样,只是类型不同而已。随着要求的不断增加,你需要更多的复制、粘贴操作。代码显的很臃肿,你可能逐渐认识到这种复制粘贴的办法不是解决问题的最好办法。
在上面的例子中,这些函数的功能一样,只是处理的数据的类型不同,有些人可能会说,为什么不使用Object来取代这些类型的差别,可是在上节中已经介绍过使用Object类型的两大弊端。所以应该采用另外的新的办法来解决这个问题。
既然一般函数中允许各种类型的变量作为参数,那么为什么类型本身不能作为参数呢?实际情况是允许的,如果一个类型作为一个函数的参数,称这样的参数为类型参数,具有类型参数的函数就是泛型函数,如果这个函数在一个类中,又称这个函数为泛型方法。类型参数是由泛型引入的一个新概念,类型参数就是一种类型占位符,在函数调用时,必须给这个类型参数指定具体的类型。于是代码可以写成例子GenericsChange中的样子
namespace GenericsChange
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
int a = 3;
int b = 5;
p.Change<int>(ref a,ref b);
Console.WriteLine("{0}<--->{1}", a, b);
char c1 = 'g';
char c2 = 'h';
p.Change<char>(ref c1, ref c2);
Console.WriteLine("{0}<--->{1}", c1, c2);
Console.ReadKey();
}
void Change<T>(ref T a,ref T b)
{
T temp;
temp = a;
a = b;
b = temp;
}
}
}
代码中加边框的部分就是一个泛型方法的定义部分,语句p.Change<int>(ref a,ref b);是对泛型方法的一个调用,或者说是泛型方法的一个实现。在实现泛型方法的时候,必须给泛型方法中的类型参数指定一个具体的类型。类型参数的命名最好采用具有一定意义的描述符比较好,而且这个描述符最好是以T开头。
当然,泛型方法中的类型参数可以不止一个,如果有多个类型描述符,它们一定要写在方法名后面紧跟的<>内,比如Change<T,U>(ref T a,ref U b )。