说明:第2部分:第12章:泛型P(185)
12.1 本章内容:
- · FCL中的泛型
- · 泛型基础接口
- · 泛型接口
- · 泛型委托
- · 委托和接口的逆变和协变泛型类型实参
- · 泛型方法
- · 泛型和其它成员
- · 可验证性和约束
/* ================================================= */ #if !DEBUG #pragma warning disable 660, 661, 219 #endif using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; public static class Generics { public static void Main() { Performance.ValueTypePerfTest(); Performance.ReferenceTypePerfTest(); GenericArray(); OpenTypes.Go(); GenericInheritance.Go(); Constraints.Go(); } /// <summary> /// ///////////////////////////////// 演示泛型方法的简单使用////////////// /// </summary> private static void GenericArray() //P238 { //创建并初始化字节数组 Byte[] byteArray = new Byte[] { 5, 1, 4, 2, 3 }; // 调用Byte[]排序算法 Array.Sort<Byte>(byteArray); // 调用Byte[]二分搜索算法 Int32 i = Array.BinarySearch<Byte>(byteArray, 1); Console.WriteLine(i); // 显示 "0" } } /// <summary> /// 性能比较 List<T> 与 ArrayList /// </summary> internal static class Performance //P235 { public static void ValueTypePerfTest() { const Int32 count = 10000000; using (new OperationTimer("List<Int32>")) { List<Int32> l = new List<Int32>(); for (Int32 n = 0; n < count; n++) { l.Add(n); // 不发生装箱 Int32 x = l[n]; // 不发生装箱 } l = null; // 确保进行垃圾回收 } using (new OperationTimer("ArrayList of Int32")) { ArrayList a = new ArrayList(); for (Int32 n = 0; n < count; n++) { a.Add(n); // 装箱 Int32 x = (Int32)a[n]; // 拆箱 } a = null; // 确保进行垃圾回收 } } public static void ReferenceTypePerfTest() { const Int32 count = 10000000; using (new OperationTimer("List<String>")) { List<String> l = new List<String>(); for (Int32 n = 0; n < count; n++) { l.Add("X"); // 复制引用 String x = l[n]; // 复制引用 } l = null; // 确保进行垃圾回收 } using (new OperationTimer("ArrayList of String")) { ArrayList a = new ArrayList(); for (Int32 n = 0; n < count; n++) { a.Add("X"); // 复制引用 String x = (String)a[n]; // 检查强制类型&复制引用 } a = null; // 确保进行垃圾回收 } } // 这个类用于进行运算性能计时 private sealed class OperationTimer : IDisposable { private Stopwatch m_stopwatch; private String m_text; private Int32 m_collectionCount; public OperationTimer(String text) { PrepareForOperation(); m_text = text; m_collectionCount = GC.CollectionCount(0); // 这个应该是方法的最后一句,从而最大程序保证计时的准确性 m_stopwatch = Stopwatch.StartNew(); } public void Dispose() { Console.WriteLine("{0} (GCs={1,3}) {2}", (m_stopwatch.Elapsed), GC.CollectionCount(0) - m_collectionCount, m_text); } private static void PrepareForOperation() { GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); } } } // /// <summary> /// 开放类型,开放类型:具有泛型类型参数的类型称为开放类型 /// </summary> internal static class OpenTypes//P239 { public static void Go() { Object o = null; // Dictionary<,> 是开放类型,有2个类型的参数 Type t = typeof(Dictionary<,>); // 尝试创建改类型的实例(失败) o = CreateInstance(t); Console.WriteLine(); // DictionaryStringKey<> 是开类型 t = typeof(DictionaryStringKey<>); // 尝试创建该类型的实例(失败) o = CreateInstance(t); Console.WriteLine(); // DictionaryStringKey<Guid> 是封闭类型 t = typeof(DictionaryStringKey<Guid>); // 尝试创建该类的一个实例(成功) o = CreateInstance(t); // 证明它确实能够工作 Console.WriteLine("Object type=" + o.GetType()); } private static Object CreateInstance(Type t) { Object o = null; try { o = Activator.CreateInstance(t); Console.Write("Created instance of {0}", t.ToString()); } catch (ArgumentException e) { Console.WriteLine(e.Message); } return o; } // 一个部分指定的开放类型 internal sealed class DictionaryStringKey<TValue> : Dictionary<String, TValue> { } } /// <summary> /// 泛型类型和继承 P(240) /// </summary> internal static class GenericInheritance { public static void Go() { /////////////看看下面2个方法///////////////////// SameDataLinkedList(); DifferentDataLinkedList(); } private static void SameDataLinkedList() { //相同数据类型的链表 Node<Char> head = new Node<Char>('C'); head = new Node<Char>('B', head); head = new Node<Char>('A', head); Console.WriteLine(head.ToString()); //这里显示“ABC” } private static void DifferentDataLinkedList() { //不能数据类型的链表 Node head = new TypedNode<Char>('.'); head = new TypedNode<DateTime>(DateTime.Now, head); head = new TypedNode<String>("Today is ", head); Console.WriteLine(head.ToString()); } private sealed class Node<T> { public T m_data; public Node<T> m_next; public Node(T data) : this(data, null) { } public Node(T data, Node<T> next) { m_data = data; m_next = next; } public override String ToString() { return m_data.ToString() + ((m_next != null) ? m_next.ToString() : null); } } private class Node { protected Node m_next; public Node(Node next) { m_next = next; } } /// <summary> /// 定义一个链表节点类 /// </summary> /// <typeparam name="T"></typeparam> private sealed class TypedNode<T> : Node { public T m_data; public TypedNode(T data) : this(data, null) { } public TypedNode(T data, Node next) : base(next) { m_data = data; } public override String ToString() { return m_data.ToString() + ((m_next != null) ? m_next.ToString() : null); } } private sealed class GenericTypeThatRequiresAnEnum<T> { static GenericTypeThatRequiresAnEnum() { if (!typeof(T).IsEnum) { throw new ArgumentException("T must be an enumerated type"); } } } } /// <summary> /// 泛型方法演示 P247 /// </summary> internal static class GenericMethods { public static void Go() { GenericType<String> gts = new GenericType<String>("123"); Int32 n = gts.Converter<Int32>(); CallingSwap(); CallingSwapUsingInference(); Display("Jeff"); // 调用 Display(String) Display(123); // 调用 Display<T>(T) Display<String>("Aidan"); // 调用 Display<T>(T) } private static void Swap<T>(ref T o1, ref T o2) { T temp = o1; o1 = o2; o2 = temp; } private static void CallingSwap() { Int32 n1 = 1, n2 = 2; Console.WriteLine("n1={0}, n2={1}", n1, n2); Swap<Int32>(ref n1, ref n2); Console.WriteLine("n1={0}, n2={1}", n1, n2); String s1 = "Aidan", s2 = "Kristin"; Console.WriteLine("s1={0}, s2={1}", s1, s2); Swap<String>(ref s1, ref s2); Console.WriteLine("s1={0}, s2={1}", s1, s2); } static void CallingSwapUsingInference() { Int32 n1 = 1, n2 = 2; Swap(ref n1, ref n2); // 调用 Swap<Int32> // String s1 = "Aidan"; // Object s2 = "Kristin"; // Swap(ref s1, ref s2); // 错误, 不能推断类型 } private static void Display(String s) { Console.WriteLine(s); } private static void Display<T>(T o) { Display(o.ToString()); // 调用 Display(String) } internal sealed class GenericType<T> { private T m_value; public GenericType(T value) { m_value = value; } public TOutput Converter<TOutput>() { TOutput result = (TOutput)Convert.ChangeType(m_value, typeof(TOutput)); return result; } } } internal static class Constraints { public static void Go() { Boolean b = ComparingGenericVariables.Op.M<ComparingGenericVariables.Op>(null, null); } private static Boolean MethodTakingAnyType<T>(T o) { T temp = o; Console.WriteLine(o.ToString()); Boolean b = temp.Equals(o); return b; } private static T Min<T>(T o1, T o2) where T : IComparable<T> { if (o1.CompareTo(o2) < 0) return o1; return o2; } private static void CallMin() { Object o1 = "Jeff", o2 = "Richter"; //Object oMin = Min<Object>(o1, o2); // Error CS0309 } internal sealed class OverloadingByArity { // 可以定义以下类型 internal sealed class AType { } internal sealed class AType<T> { } internal sealed class AType<T1, T2> { } // 错误:与没有约束的AType<T>冲突 //internal sealed class AType<T> where T : IComparable<T> { } // 错误: 与AType<T1, T2> 冲突 //internal sealed class AType<T3, T4> { } internal sealed class AnotherType { //可以定义以下方法,参数个数不同 private static void M() { } private static void M<T>() { } private static void M<T1, T2>() { } // 错误: 与没有约束 M<T> 冲突 //private static void M<T>() where T : IComparable<T> { } // 错误: 月 M<T1, T2> 冲突 //private static void M<T3, T4>() { } } } internal static class OverridingVirtualGenericMethod { internal class Base { public virtual void M<T1, T2>() where T1 : struct where T2 : class { } } internal sealed class Derived : Base { public override void M<T3, T4>() /*where T3 : struct //错误 where T4 : class */ //错误 { } } } /// <summary> /// 主要约束演示 P252 /// </summary> internal static class PrimaryConstraints { internal static class PrimaryConstraintOfStream<T> where T : Stream { public static void M(T stream) { stream.Close(); // 正确 } } internal static class PrimaryConstraintOfClass<T> where T : class // P252 { public static void M() { #pragma warning disable 219 T temp = null; // 允许,因为T肯定是引用类型 #pragma warning restore 219 } } internal static class PrimaryConstraintOfStruct<T> where T : struct//P253 { public static T Factory() { // 允许,因为所有的值类型都隐式有一个公共无参构造器 return new T(); } } } /// <summary> /// 次要约束 P253 /// </summary> internal static class SecondaryConstraints { private static List<TBase> ConvertIList<T, TBase>(IList<T> list) where T : TBase { List<TBase> baseList = new List<TBase>(list.Count); for (Int32 index = 0; index < list.Count; index++) { baseList.Add(list[index]); } return baseList; } private static void CallingConvertIList() { // 构造并初始化一个List<string>(它实现了IList<String>) IList<String> ls = new List<String>(); ls.Add("A String"); // 1.将 IList<String> 转化成 IList<Object> IList<Object> lo = ConvertIList<String, Object>(ls); // 2. 将<String> 转化成 <IComparable> IList<IComparable> lc = ConvertIList<String, IComparable>(ls); // 3.将 IList<String>转化成<IComparable<String>> IList<IComparable<String>> lcs = ConvertIList<String, IComparable<String>>(ls); // 4.将 IList<String>转化成<Exception>这里就出错误,string 不兼容 Exception,具体解释P254 //IList<Exception> le = ConvertIList<String, Exception>(ls); // 这里就出错误。 } } /// <summary> /// 构造器约束P254 /// </summary> internal sealed class ConstructorConstraints { internal sealed class ConstructorConstraint<T> where T : new() { public static T Factory() { //允许,因为所有值类型都隐式有个一个公共无参数构造器 //而如果指定的是引用类型,约束也要求它提供公共无参构造器 return new T(); } } } internal sealed class CastingAGenericTypeVariable { private void CastingAGenericTypeVariable1<T>(T obj) { //Int32 x = (Int32)obj; // 错误 T可能是任意类型 //String s = (String)obj; // 错误 } private void CastingAGenericTypeVariable2<T>(T obj) { Int32 x = (Int32)(Object)obj; // 只是编译不错误,但是实际允许有可能报错 String s = (String)(Object)obj; // 只是编译不错误,但是实际允许有可能报错 } private void CastingAGenericTypeVariable3<T>(T obj) { String s = obj as String; // 没有错误 } } internal sealed class SettingAGenericTypeVariableToADefaultValue { private void SettingAGenericTypeVariableToNull<T>() { //T temp = null; // 错误将泛型设置为NULL是非法,除非将泛型约束成引用类型。请考虑改用defalut(T) } private void SettingAGenericTypeVariableToDefaultValue<T>() { #pragma warning disable 219 T temp = default(T); //如果是引用类型就NULL,如果值类型就0 #pragma warning restore 219 } } internal sealed class ComparingGenericVariables { private void ComparingAGenericTypeVariableWithNull<T>(T obj) { if (obj == null) { /* 对于值类型是永远不会执行 */ } } private void ComparingTwoGenericTypeVariables<T>(T o1, T o2) { //if (o1 == o2) { } // 泛型之间比较是非法的。 } #pragma warning disable 660, 661 internal class Op { public static Boolean operator ==(Op o1, Op o2) { return true; } public static Boolean operator !=(Op o1, Op o2) { return false; } public static Boolean M<T>(T o1, T o2) where T : Op { return o1 == o2; } } #pragma warning restore 660, 661 } } #if false //泛型类型变量作为操作符使用 ,这里的方法会报错。即使将T 约束成值类型,和 n初始化0, internal static class UsingGenericTypeVariablesAsOperands { private T Sum<T>(T num) where T : struct { T sum = default(T); for (T n = default(T); n < num; n++) sum += n; return sum; } } #endif