C#基础-第12章:泛型


说明:第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();
    }

    /// 
    /// / 演示泛型方法的简单使用//
    /// 
    private static void GenericArray() //P238
    {
        //创建并初始化字节数组
        Byte[] byteArray = new Byte[] { 5, 1, 4, 2, 3 };

        // 调用Byte[]排序算法
        Array.Sort(byteArray);

        // 调用Byte[]二分搜索算法
        Int32 i = Array.BinarySearch(byteArray, 1);

        Console.WriteLine(i);   // 显示 "0"
    } 

}

/// 
/// 性能比较 List 与 ArrayList
/// 
internal static class Performance //P235
{
    public static void ValueTypePerfTest()
    {
        const Int32 count = 10000000;

        using (new OperationTimer("List"))
        {
            List l = new List();
            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"))
        {
            List l = new List();
            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();
        }
    }
} //

/// 
/// 开放类型,开放类型:具有泛型类型参数的类型称为开放类型
/// 
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 是封闭类型
        t = typeof(DictionaryStringKey);

        // 尝试创建该类的一个实例(成功)
        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 :
       Dictionary
    {
    }
}

/// 
/// 泛型类型和继承 P(240)
/// 
internal static class GenericInheritance
{
    public static void Go()
    {
        /看看下面2个方法/

        SameDataLinkedList();
        DifferentDataLinkedList();
    }

    private static void SameDataLinkedList()
    {
        //相同数据类型的链表
        Node head = new Node('C');
        head = new Node('B', head);
        head = new Node('A', head);
        Console.WriteLine(head.ToString()); //这里显示“ABC”
    }

    private static void DifferentDataLinkedList()
    {
        //不能数据类型的链表

        Node head = new TypedNode('.');
        head = new TypedNode(DateTime.Now, head);
        head = new TypedNode("Today is ", head);
        Console.WriteLine(head.ToString());
    }

    private sealed class Node
    {
        public T m_data;
        public Node m_next;

        public Node(T data)
           : this(data, null)
        {
        }

        public Node(T data, Node 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;
        }
    }

    /// 
    /// 定义一个链表节点类
    /// 
    /// 
    private sealed class TypedNode : 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
    {
        static GenericTypeThatRequiresAnEnum()
        {
            if (!typeof(T).IsEnum)
            {
                throw new ArgumentException("T must be an enumerated type");
            }
        }
    }
}

/// 
/// 泛型方法演示 P247
/// 
internal static class GenericMethods
{
    public static void Go()
    {
        GenericType gts = new GenericType("123");
        Int32 n = gts.Converter();

        CallingSwap();
        CallingSwapUsingInference();

        Display("Jeff");           // 调用 Display(String)
        Display(123);              // 调用 Display(T)
        Display("Aidan");  // 调用 Display(T)
    }

    private static void Swap(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(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(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

        // 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 o)
    {
        Display(o.ToString());  // 调用 Display(String)
    }

    internal sealed class GenericType
    {
        private T m_value;

        public GenericType(T value) { m_value = value; }

        public TOutput Converter()
        {
            TOutput result = (TOutput)Convert.ChangeType(m_value, typeof(TOutput));
            return result;
        }
    }
}

internal static class Constraints
{
    public static void Go()
    {
        Boolean b = ComparingGenericVariables.Op.M(null, null);
    }

    private static Boolean MethodTakingAnyType(T o)
    {
        T temp = o;
        Console.WriteLine(o.ToString());
        Boolean b = temp.Equals(o);
        return b;
    }

    private static T Min(T o1, T o2) where T : IComparable
    {
        if (o1.CompareTo(o2) < 0) return o1;
        return o2;
    }

    private static void CallMin()
    {
        Object o1 = "Jeff", o2 = "Richter";
        //Object oMin = Min(o1, o2);    // Error CS0309
    }

    internal sealed class OverloadingByArity
    {
        // 可以定义以下类型
        internal sealed class AType { }
        internal sealed class AType { }
        internal sealed class AType { }

        // 错误:与没有约束的AType冲突
        //internal sealed class AType where T : IComparable { }

        // 错误: 与AType 冲突
        //internal sealed class AType { }

        internal sealed class AnotherType
        {
            //可以定义以下方法,参数个数不同
            private static void M() { }
            private static void M() { }
            private static void M() { }

            // 错误: 与没有约束 M 冲突
            //private static void M() where T : IComparable { }

            // 错误: 月 M 冲突
            //private static void M() { }
        }
    }

    internal static class OverridingVirtualGenericMethod
    {
        internal class Base
        {
            public virtual void M()
               where T1 : struct
               where T2 : class
            {
            }
        }

        internal sealed class Derived : Base
        {
            public override void M()
            /*where T3 : struct         //错误
            where T4 : class  */        //错误
            {
            }
        }
    }

    /// 
    /// 主要约束演示 P252
    /// 
    internal static class PrimaryConstraints
    {
        internal static class PrimaryConstraintOfStream where T : Stream
        {
            public static void M(T stream)
            {
                stream.Close();   // 正确
            }
        }

        internal static class PrimaryConstraintOfClass where T : class   // P252
        {
            public static void M()
            {
#pragma warning disable 219
                T temp = null;  // 允许,因为T肯定是引用类型
#pragma warning restore 219
            }
        }

        internal static class PrimaryConstraintOfStruct where T : struct//P253
        {
            public static T Factory()
            {
                // 允许,因为所有的值类型都隐式有一个公共无参构造器
                return new T();
            }
        }
    }

    /// 
    /// 次要约束 P253
    /// 
    internal static class SecondaryConstraints
    {
        private static List ConvertIList(IList list)
           where T : TBase
        {

            List baseList = new List(list.Count);
            for (Int32 index = 0; index < list.Count; index++)
            {
                baseList.Add(list[index]);
            }
            return baseList;
        }

        private static void CallingConvertIList() 
        {
            // 构造并初始化一个List(它实现了IList)
            IList ls = new List();
            ls.Add("A String");

            // 1.将 IList 转化成 IList
            IList lo = ConvertIList(ls);

            // 2. 将 转化成 
            IList lc = ConvertIList(ls);

            // 3.将 IList转化成>
            IList> lcs =
               ConvertIList>(ls);


            // 4.将 IList转化成这里就出错误,string 不兼容 Exception,具体解释P254
            //IList le = ConvertIList(ls);    // 这里就出错误。
        }
    }

    /// 
    /// 构造器约束P254
    /// 
    internal sealed class ConstructorConstraints
    {
        internal sealed class ConstructorConstraint where T : new()
        {
            public static T Factory()
            {
                //允许,因为所有值类型都隐式有个一个公共无参数构造器
                //而如果指定的是引用类型,约束也要求它提供公共无参构造器
                return new T();
            }
        }
    }


    internal sealed class CastingAGenericTypeVariable
    {
        private void CastingAGenericTypeVariable1(T obj)
        {
            //Int32 x = (Int32)obj;    // 错误 T可能是任意类型
            //String s = (String)obj;  // 错误
        }
        private void CastingAGenericTypeVariable2(T obj)
        {
            Int32 x = (Int32)(Object)obj;    // 只是编译不错误,但是实际允许有可能报错
            String s = (String)(Object)obj;  // 只是编译不错误,但是实际允许有可能报错
        }
        private void CastingAGenericTypeVariable3(T obj)
        {
            String s = obj as String;  // 没有错误
        }
    }

    internal sealed class SettingAGenericTypeVariableToADefaultValue
    {
        private void SettingAGenericTypeVariableToNull()
        {
            //T temp = null;    // 错误将泛型设置为NULL是非法,除非将泛型约束成引用类型。请考虑改用defalut(T)
        }

        private void SettingAGenericTypeVariableToDefaultValue()
        {
#pragma warning disable 219
            T temp = default(T);    //如果是引用类型就NULL,如果值类型就0
#pragma warning restore 219
        }
    }

    internal sealed class ComparingGenericVariables
    {
        private void ComparingAGenericTypeVariableWithNull(T obj)
        {
            if (obj == null) { /* 对于值类型是永远不会执行 */ }
        }
        private void ComparingTwoGenericTypeVariables(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 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 num) where T : struct {
      T sum = default(T);
      for (T n = default(T); n < num; n++)
         sum += n;
      return sum;
   }
}
#endif

 

转载于:https://www.cnblogs.com/eric-yuan/p/10302772.html

你可能感兴趣的:(数据结构与算法)