C# 泛型有多少个类?
有这样一个需求:通过反射获取类类型中指定名字的方法信息,实现如下,
public class NormalClass {
public MethodInfo GetMethodInfo(Type classType, string methodName) {
MethodInfo methodInfo;
methodInfo = classType.GetMethod(methodName, BindingFlags .Public | BindingFlags .Instance);
return methodInfo;
}
}
这个需求看起来很简单,但是调用的地方和传的 classType 是相当的多,于是考虑到缓存,创建一个全局字典,用于存储类的方法信息,GetMethodInfo() 方法从类字典中试着获取类对应的方法列表,如果不存在,则创建方法列表并加到字曲中供下次获取,这样就不用相同类每次都创建,起到缓存作用。现在的实现看起来如下,
public class NormalClass {
private static object __lockObject = new object ();
private static Dictionary <Type , List <MethodInfo >> __typeList = new Dictionary <Type , List <MethodInfo >>();
private List <MethodInfo > _methodList;
public NormalClass(Type classType) {
lock (__lockObject) {
if (!__typeList.TryGetValue(classType, out _methodList)) {
lock (__lockObject) {
_methodList = new List <MethodInfo >();
__typeList.Add(classType, _methodList);
MethodInfo [] methodInfos = classType.GetMethods(BindingFlags .Instance | BindingFlags .Public);
foreach (MethodInfo methodInfo in methodInfos) {
_methodList.Add(methodInfo);
}
}
}
}
}
public MethodInfo GetMethodInfo(string methodName) {
foreach (MethodInfo methodInfo in _methodList) {
if (methodInfo.Name.Equals(methodName)){
return methodInfo;
}
}
return null ;
}
}
好了,功能实现了,编写调用语句,
NormalClass normalClass1 = new NormalClass (typeof (TestClass1 ));
MethodInfo methodInfo = normalClass1.GetMethodInfo("TestMethod" );
调用也OK ,一切正常,需求完成。这时,另外一个人用泛型方式实现了另一个类,新类看起来如下,
public class GeneralizationClass <T> where T : class {
private static object __lockObject = new object ();
private static Dictionary <Type , List <MethodInfo >> __typeList = new Dictionary <Type , List <MethodInfo >>();
private List <MethodInfo > _methodList;
public GeneralizationClass() {
lock (__lockObject) {
Type classType = typeof (T);
if (!__typeList.TryGetValue(classType, out _methodList)) {
lock (__lockObject) {
_methodList = new List <MethodInfo >();
__typeList.Add(classType, _methodList);
MethodInfo [] methodInfos = classType.GetMethods(BindingFlags .Instance | BindingFlags .Public);
foreach (MethodInfo methodInfo in methodInfos) {
_methodList.Add(methodInfo);
}
}
}
}
}
public MethodInfo GetMethodInfo(string methodName) {
foreach (MethodInfo methodInfo in _methodList) {
if (methodInfo.Name.Equals(methodName)){
return methodInfo;
}
}
return null ;
}
}
用泛型实现的类也能做相同的事情,看起来好象没什么问题,运行也正常,调用语句象下面这样,
GeneralizationClass <TestClass1 > genClass1 = new GeneralizationClass <TestClass1 >();
MethodInfo methodInfo = genClass1.GetMethodInfo("TestMethod" );
但是,用泛型实现的类,存在一个很大的问题,就是如果指派给泛型类的类类型不同,则泛型对象的类型是不同的,就如下面语句,typeEqual 变量的值为 false ,
GeneralizationClass <TestClass1 > genClass1 = new GeneralizationClass <TestClass1 >();
GeneralizationClass <TestClass2 > genClass2 = new GeneralizationClass <TestClass2 >();
bool typeEqual = genClass1.GetType() == genClass2.GetType();
这就是说,指派给泛型类的类类型有多少个,则就有多少个不同的类型,而泛型类内部的缓存字典,也会不同,因为是完全不同的类了。
现在才进入要表达的主题 J
为了验证上面的观点,我们分别在普通类和泛型类上增加一个静态属性,用于获取多次调用后,字典中的 Type 数,实现如下,
public static int TypeCount{
get {
return __typeList.Count;
}
}
然后,我们编写下面的语句进行测试,测试结果在每条语句的注释中,
private void button1_Click(object sender, EventArgs e) {
NormalClass normalClass1;
NormalClass normalClass2;
NormalClass normalClass3;
NormalClass normalClass4;
int typeCount;
normalClass1 = new NormalClass (typeof (TestClass1 ));
typeCount = NormalClass .TypeCount; // typeCount == 1
normalClass2 = new NormalClass (typeof (TestClass2 ));
typeCount = NormalClass .TypeCount; // typeCount == 2
normalClass1 = new NormalClass (typeof (TestClass1 ));
typeCount = NormalClass .TypeCount; // typeCount == 2
normalClass3 = new NormalClass (typeof (TestClass3 ));
typeCount = NormalClass .TypeCount; // typeCount == 3
normalClass4 = new NormalClass (typeof (TestClass4 ));
typeCount = NormalClass .TypeCount; // typeCount == 4
normalClass1 = new NormalClass (typeof (TestClass1 ));
typeCount = NormalClass .TypeCount; // typeCount == 4
normalClass3 = new NormalClass (typeof (TestClass3 ));
typeCount = NormalClass .TypeCount; // typeCount == 4
// 对比类类型是否相等
bool typeEqual;
typeEqual = normalClass1.GetType() == normalClass2.GetType(); // typeEqual == true
typeEqual = normalClass1.GetType() == normalClass3.GetType(); // typeEqual == true
typeEqual = normalClass1.GetType() == normalClass4.GetType(); // typeEqual == true
typeEqual = normalClass2.GetType() == normalClass3.GetType(); // typeEqual == true
}
private void button2_Click(object sender, EventArgs e) {
GeneralizationClass <TestClass1 > genClass1;
GeneralizationClass <TestClass2 > genClass2;
GeneralizationClass <TestClass3 > genClass3;
GeneralizationClass <TestClass4 > genClass4;
int typeCount;
genClass1 = new GeneralizationClass <TestClass1 >();
typeCount = GeneralizationClass <TestClass1 >.TypeCount; // typeCount == 1
genClass2 = new GeneralizationClass <TestClass2 >();
typeCount = GeneralizationClass <TestClass2 >.TypeCount; // typeCount == 1
genClass1 = new GeneralizationClass <TestClass1 >();
typeCount = GeneralizationClass <TestClass1 >.TypeCount; // typeCount == 1
genClass3 = new GeneralizationClass <TestClass3 >();
typeCount = GeneralizationClass <TestClass3 >.TypeCount; // typeCount == 1
genClass4 = new GeneralizationClass <TestClass4 >();
typeCount = GeneralizationClass <TestClass4 >.TypeCount; // typeCount == 1
genClass1 = new GeneralizationClass <TestClass1 >();
typeCount = GeneralizationClass <TestClass1 >.TypeCount; // typeCount == 1
genClass3 = new GeneralizationClass <TestClass3 >();
typeCount = GeneralizationClass <TestClass3 >.TypeCount; // typeCount == 1
// 对比类类型是否相等
bool typeEqual;
typeEqual = genClass1.GetType() == genClass2.GetType(); // typeEqual == false
typeEqual = genClass1.GetType() == genClass3.GetType(); // typeEqual == false
typeEqual = genClass1.GetType() == genClass4.GetType(); // typeEqual == false
typeEqual = genClass2.GetType() == genClass3.GetType(); // typeEqual == false
}
}
通过上面的测试语句,相信大家已经明白。