这篇博客就C#的特性--泛型(Generic)做一下简单介绍:
学过C++的朋友应该都知道C++模板(Template)这一特性,C#中的泛型相当于C++中的模板。
(一).在介绍泛型之前,我们先考虑以下情况:
假设我们现在需要写一个比较类,这个类需要对传入的两个double类型的数据进行比较大小操作,实现代码如下:
public class DoubleCompare
{
private double x,y;
public void Compare(double a,double b)//赋值函数
{
x=a;
y=b;
}
public double Max()//返回较大值
{
return (x>y)?x:y;
}
public double Min()//返回较小值
{
return (x<y)?x:y;
}
}
Main函数调用如下:
static void Main(string[] args)
{
DoubleCompare compare = double DoubleCompare();
double a = 3;
double b = 4;
compare.Compare(a,b);
double max = compare.Max();
double min = compare.Min();
Console.Write("Max:" + max + " Min:" + min);
Console.ReadKey();
}
运行结果如下:
这时,假如我们还需要一个相似的比较类,功能与DoubleCompare类相同,只是要处理的是两个String类型的字符,这时我们需要再写一个StringCompare类,代码如下:
public class StringCompare
{
private string x,y;
public void Compare(string a,string b)//赋值函数
{
x=a;
y=b;
}
public string Max()//返回较大值
{
return (string.Compare(x,y) > 0) ? x : y;
}
public string Min()//返回较小值
{
return (string.Compare(x,y) < 0) ? x : y;
}
}
我们可以看到,两个类的功能完全一致只是处理数据的类型不一样。但没有办法,因为类中方法的参数类型不同,只能写多个类分别处理每个数据类型,这就造成了代码的冗余和不必要的开销。
(二).
有没有一种办法,在方法中传入通用的数据类型,实现一类多用,这样不就可以合并代码了吗?泛型的出现就是专门解决这个问题的。
我们先用泛型写出一个通用类:
public class GenericCompare<T> where T : IComparable
{
private T x,y;
public void Compare(T a,T b)//复制函数
{
x=a;
y=b;
}
public T Max()//返回较大值
{
return (x.CompareTo(y) > 0) ? x : y;
}
public T Min()//返回较小值
{
return (x.CompareTo(y) < 0) ? x : y;
}
}
注意这句代码:
public class GenericCompare<T> where T : IComparable
我们注意到,泛型类在声明时类名后多了一对尖括号<>,里面的类型T就是通用类型,在初始化类对象时T可以是Double、String或者其他类型。
因为要对元素进行比较,所以泛型要约束成实现IComparable接口:
where T : IComparable
接下来,我们再修改Main函数,
static void Main(string[] args)
{
//实例化泛型的类对象时也需要用<>表示对象的类型
GenericCompare<double> double_compare = new GenericCompare<double>();
GenericCompare<string> string_compare = new GenericCompare<string>();
double a = 3;
double b = 4;
string c = "C";
string d = "D";
double_compare.Compare(a, b);
string_compare.Compare(c, d);
double max1 = double_compare.Max();
double min1 = double_compare.Min();
string max2 = string_compare.Max();
string min2 = string_compare.Min();
Console.Write("Max1:" + max1 + " Min1:" + min1 + "\n");
Console.Write("Max2:" + max2 + " Min2:" + min2 + "\n");
Console.ReadKey();
}
运行结果如下:
我们可以看到,在实例化泛型的类对象时也需要用<>表示对象的类型。
C#泛型类在编译时,先生成中间代码,通用类型T只是一个占位符。在实例化类时,根据用户指定的数据类型代替T并由即时编译器生成本地代码,这个本地代码中已经使用了实际的数据类型,等同于用实际类型写的类,所以不同的封闭类的本地代码是不一样的。按照这个原理,我们可以这样认为:
泛型类的不同的封闭类是分别不同的数据类型。
例如GenericCompare<double>和GenericCompare<string>是两个完全没有任何关系的类,你可以把他看成类A和类B。
以上。