在谈泛型的时候,必须说起C#的四种数值类型:即引用类型、(数)值类型、结构类型以及枚举类型,大多数人会将(数)值类型和结构类型统称为值类型。前面一直在说,使用泛型会大大提高程序的执行效率,之前一直没讲?现在来说一下其中的一个原因。IDE运行C#代码时,首先会将其解析成IL形式的程序集,然后才加载至内存的数据页,最后JIT编译器将IL转换成机器指令,生成的机器码才会被放置于只读的代码页中(因为我们的电脑只认识机器码,编程语言太高级了,它不认识)。
对于非泛型类型,类的IL和其生成的机器码之间是一对的关系。
JIT对泛型进行转换时,JIT将检查当前的类型参数,并根据该信息生成特定的指令,以便让不同类型参数能够使用同样的机器码。请记住,JIT会为所有的引用类型生成泛型类的一个机器码版本(引用类型才会,值类型不管)。
List<string> stringList=new List<string>();
List<ClassType> otherList=new List<ClassType>(); //这里的IL代码是一样的
下面是一个使用XML序列化器对对象进行序列化,而非泛型的版本将允许传入任何类型。
public static object LoadFromFile(Type typeToLoad, string filePath) { XmlSerializer factory = new XmlSerializer(typeToLoad); if (File.Exists(filePath)) { using (TextReader r = new StreamReader(filePath)) { object rval = factory.Deserialize(r); return rval; } } return default(object); } public static void SaveToFile(string filePath, object obj) { Type theType = obj.GetType(); XmlSerializer factory = new XmlSerializer(theType); using (TextWriter w = new StreamWriter(filePath, false)) { factory.Serialize(w, obj); } }
也许有人不清楚Default的用法,这里插上一句,Default在泛型类和泛型方法中,在预先未参数类型时,将默认值分配给参数化类型 T。请看下面一个例子,可以很清楚的了解Default的功能。
泛型类GenericList类似泛型的Add功能,将值插入到类似链表中的结构中。
public class GenericList<T> { private class Node { public Node Next; public T Data; } private Node head = null; public void AddNode(T t) { Node newNode = new Node(); newNode.Next = head; newNode.Data = t; head = newNode; } public T GetLast() { T temp = default(T); Node current = head; while (current != null) { temp = current.Data; current = current.Next; } return temp; } }
主函数Main
GenericList<int> gl1 = new GenericList<int>(); gl1.AddNode(5); gl1.AddNode(4); gl1.AddNode(3); int intVal = gl1.GetLast(); Console.WriteLine(intVal); GenericList<int> gl2 = new GenericList<int>(); intVal = gl2.GetLast(); Console.WriteLine(intVal); GenericList<string> gl3 = new GenericList<string>(); GenericList<TestClass> xmls = new GenericList<TestClass>(); gl3.AddNode("five"); gl3.AddNode("fou"); string sVal = gl3.GetLast(); Console.WriteLine(sVal); GenericList<string> gll4 = new GenericList<string>(); sVal = gll4.GetLast(); Console.WriteLine(sVal); Console.WriteLine("end");
这里的返回值为5,0,five, 。没错,你没看错,最后返回的一个值是空的字符串。
在MSDN中对Default的解释为Default的作用是
给定参数化类型 T 的一个变量 t,只有当 T 为引用类型时,语句 t = null 才有效;只有当 T 为数值类型而不是结构时,语句 t = 0 才能正常使用。 解决方案是使用 default 关键字,此关键字对于引用类型会返回 null,对于数值类型会返回零。 对于结构,此关键字将返回初始化为零或 null 的每个结构成员,具体取决于这些结构是值类型还是引用类型。 对于可以为 null 的值类型,默认返回 System.Nullable(Of T),它像任何结构一样初始化。
这里暂时回到上面的XML序列化器的代码中,上面的序列化器中的代码你看出了什么问题吗?当然,请你用需求变化的眼观看待,否则,你看不出有什么问题,因为语法都是完全正确的,如何改进上述的序列类,后一篇我继续讲到。