C#学习系列之---泛型

1.如何声明和使用泛型

泛型是C#2.0和CLR(公共语言运行时)升级的一个新特性,泛型 为.NET 框架引入了一个叫 type parameters(类型参数)的概念,type parameters 使得程序在设计的时候,不必设计其具体的参数,其具体的参数可以延迟到需要的时候声明或调用。使用泛型代码运行时避免了类型转换的装箱和拆箱操作。

 public class CommonMethod
 {
     /// <summary>
     /// 打印个int值
     /// </summary>
     /// <param name="iParameter"></param>
     public static void ShowInt(int iParameter)
     {
         Console.WriteLine("This is {0},parameter={1},type={2}",
             typeof(CommonMethod).Name, iParameter.GetType().Name, iParameter);
     }

     /// <summary>
     /// 打印个string值
     /// </summary>
     /// <param name="sParameter"></param>
     public static void ShowString(string sParameter)
     {
         Console.WriteLine("This is {0},parameter={1},type={2}",
             typeof(CommonMethod).Name, sParameter.GetType().Name, sParameter);
     }

     /// <summary>
     /// 打印个DateTime值
     /// </summary>
     /// <param name="oParameter"></param>
     public static void ShowDateTime(DateTime dtParameter)
     {
         Console.WriteLine("This is {0},parameter={1},type={2}",
             typeof(CommonMethod).Name, dtParameter.GetType().Name, dtParameter);
     }


     /// <summary>
     /// 打印个object值
     /// 1 object类型是一切类型的父类
     /// 2 任何父类出现的地方,都可以用子类来代替
     /// </summary>
     /// <param name="oParameter"></param>
     public static void ShowObject(object oParameter)
     {
         Console.WriteLine("This is {0},parameter={1},type={2}",
             typeof(CommonMethod), oParameter.GetType().Name, oParameter);
     }

     /// <summary>
     /// 
     /// </summary>
     /// <typeparam name="T"></typeparam>
     /// <param name="tParameter"></param>
     public static void Show<T>(T tParameter)
     {
         Console.WriteLine("This is {0},parameter={1},type={2}",
             typeof(GenericMethod), tParameter.GetType().Name, tParameter.ToString());
     }
 }
	class Program
    {
        static void Main(string[] args)
        {
            try
            {

                int iValue = 123;
                string sValue = "456";
                DateTime dtValue = DateTime.Now;
                object oValue = "789";

                Console.WriteLine("**************************");
                CommonMethod.ShowInt(iValue);
                //CommonMethod.ShowInt(sValue);//类型必须吻合
                CommonMethod.ShowString(sValue);
                CommonMethod.ShowDateTime(dtValue);

                Console.WriteLine("**************************");
                CommonMethod.ShowObject(oValue);
                CommonMethod.ShowObject(iValue);
                CommonMethod.ShowObject(sValue);
                CommonMethod.ShowObject(dtValue);

                Console.WriteLine("**************************");
                CommonMethod.Show<object>(oValue);
                CommonMethod.Show<int>(iValue);
                CommonMethod.Show(iValue);//可以去掉,自动推算
                //GenericMethod.Show<string>(iValue);//必须匹配
                CommonMethod.Show<string>(sValue);
                CommonMethod.Show<DateTime>(dtValue);
            }
        }
    }

在这里插入图片描述
性能测试代码:

	/// <summary>
    /// 性能对比
    /// </summary>
    public class Monitor
    {
        public static void Show()
        {
            Console.WriteLine("****************Monitor******************");
            {
                int iValue = 12345;
                long commonSecond = 0;
                long objectSecond = 0;
                long genericSecond = 0;

                {
                    Stopwatch watch = new Stopwatch();
                    watch.Start();
                    for (int i = 0; i < 100000000; i++)
                    {
                        ShowInt(iValue);
                    }
                    watch.Stop();
                    commonSecond = watch.ElapsedMilliseconds;
                }
                {
                    Stopwatch watch = new Stopwatch();
                    watch.Start();
                    for (int i = 0; i < 100000000; i++)
                    {
                        ShowObject(iValue);
                    }
                    watch.Stop();
                    objectSecond = watch.ElapsedMilliseconds;
                }
                {
                    Stopwatch watch = new Stopwatch();
                    watch.Start();
                    for (int i = 0; i < 100000000; i++)
                    {
                        Show<int>(iValue);
                    }
                    watch.Stop();
                    genericSecond = watch.ElapsedMilliseconds;
                }
                Console.WriteLine("commonSecond={0},objectSecond={1},genericSecond={2}"
                    , commonSecond, objectSecond, genericSecond);
            }
        }

        #region PrivateMethod
        private static void ShowInt(int iParameter)
        {
            //do nothing
        }
        private static void ShowObject(object oParameter)
        {
            //do nothing
        }
        private static void Show<T>(T tParameter)
        {
            //do nothing
        }
        #endregion

    }

在这里插入图片描述

3.泛型类, 泛型方法,泛型接口,泛型委托

    /// <summary>
    /// 泛型:就是为了满足不同类型,相同代码的重用
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class GenericClass<T>
    {
        public T Property { get; set; }

        /// <summary>
        /// 泛型方法声明的时候,没有指定类型,而是调用的时候指定
        /// 2.0泛型不是语法糖,而是由框架升级提供的功能
        /// 泛型方法性能上和普通方法差不多的
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static void Show<T>(T tParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(GenericMethod), tParameter.GetType().Name, tParameter.ToString());
        }
    }

    /// <summary>
    /// 泛型接口
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IGenericInterface<T>
    {

    }

    /// <summary>
    /// 泛型委托
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public delegate void DoNothing<T>();

    /// <summary>
    /// 普通类
    /// </summary>
    public class ChildClass : GenericClass<int>, IGenericInterface<string>//指定类型后的泛型,已经不是泛型的
    {

    }
    public class ChildClassGeneric<T, S, V> : GenericClass<T>, IGenericInterface<S>
    {

    }
List<int> intList = new List<int>();
List<string> stringList = new List<string>();
//调用泛型类
GenericClass<int> iGenericClass = new GenericClass<int>();
iGenericClass.Property = 1;

GenericClass<string> sGenericClass = new GenericClass<string>();
sGenericClass.Property = "1233";
//普通类
ChildClass child = new ChildClass();
child.Property = 1;

ChildClassGeneric<int, string, DateTime> childClassGeneric = new ChildClassGeneric<int, string, DateTime>();
//委托
DoNothing<int> method = new DoNothing<int>(() => { });

3.泛型约束

	public interface ISports
    {
        void Pingpang();
    }

    public interface IWork
    {
        void Work();
    }


    public class People
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public void Hi()
        { }
    }

    public class Chinese : People, ISports, IWork
    {
        public void Tradition()
        {
            Console.WriteLine("仁义礼智信,温良恭俭让");
        }
        public void SayHi()
        {
            Console.WriteLine("吃了么?");
        }

        public void Pingpang()
        {
            Console.WriteLine("打乒乓球...");
        }

        public void Work()
        {
            throw new NotImplementedException();
        }
    }

    public class Hubei : Chinese
    {

        public Hubei(int id)
        {
        }
        public string Changjiang { get; set; }
        public void Majiang()
        {
            Console.WriteLine("打麻将啦。。");
        }
    }


    public class Japanese : ISports
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public void Pingpang()
        {
            Console.WriteLine("打乒乓球...");
        }
        public void Hi()
        { }
    }
    public class Constraint
    {
        /// <summary>
        /// 代码编译没问题,执行的时候才报错
        /// 代码安全问题
        /// </summary>
        /// <param name="oParameter"></param>
        public static void ShowObject(object oParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod), oParameter.GetType().Name, oParameter);

            People people = (People)oParameter;

            Console.WriteLine(people.Id);
            Console.WriteLine(people.Name);
        }

        /// <summary>
        /// 基类约束:
        /// 1 带来权力,可以使用基类里面的属性和方法
        /// 2 带来义务,类型参数必须是基类或者其子类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static void Show<T>(T tParameter)
            where T : People, ISports, new()//都是and 关系
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(GenericMethod), tParameter.GetType().Name, tParameter.ToString());

            Console.WriteLine(tParameter.Id);
            Console.WriteLine(tParameter.Name);
            tParameter.Hi();
            tParameter.Pingpang();
            T t = new T();
        }

        public static void ShowPeople(People tParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(GenericMethod), tParameter.GetType().Name, tParameter.ToString());

            Console.WriteLine(tParameter.Id);
            Console.WriteLine(tParameter.Name);
            tParameter.Hi();
            //tParameter.Pingpang();
        }

        public static T DoNothing<T>(T tParameter)
            //where T : ISports//接口约束
            //where T : class//引用类型约束
            //where T : struct//值类型约束
            where T : new()//无参数构造函数约束
        {
            //tParameter.Pingpang();
            //return null;
            T t = new T();
            return default(T);//会根据T的类型,去产生一个默认值
        }
    }

4.泛型的好处和原理

1)性能
  对值类型使用非泛型集合类,在把值类型转换为引用类型,和把引用类型转换为值类型时,需要进行装箱和拆箱操作。装箱和拆箱的操作很容易实现,但是性能损失较大。假如使用泛型,就可以避免装箱和拆箱操作。
  
2)类型安全
  与ArrayList类一样,如果使用对象,可以在这个集合中添加任意类型。
  如果使用非泛型编程,如下代码,就有可能在某些情况下会发生异常。
  
3)二进制代码重用
  泛型可以定义一次,用许多不同的类型实例化,不需要像C++模板那样访问源代码。泛型可以在一种语言中定义,在另一种.NET语言中使用。

4)代码的扩展
  因为泛型类的定义会放在程序集中,所以用某个类型实例化泛型泛型类不会在IL代码中复制这些类。但是,在JIT编译器把泛型类编译为内部代码时,会给每个值类型创建一个新类。引用类型共享同一个内部类的所有实现代码。这是因为引用类型在实例化的泛型类中只需要4字节的内存单元(32位系统),就可以引用一个引用类型。值类型包含在实例化的泛型类的内存中。而每个值类型对内存的要求都不同,所以要为每个值类型实例化一个新类。

发布了37 篇原创文章 · 获赞 3 · 访问量 6327

猜你喜欢

转载自blog.csdn.net/huan13479195089/article/details/89026071