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();
    }

    /// <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

猜你喜欢

转载自www.cnblogs.com/eric-yuan/p/10302772.html