一 泛型 c#基础学习 [实操上手笔记]

164 阅读2分钟

一 啥是泛型。

创建一个控制台项目 (过程略。)

1 先从体验一个类 showX 参数类型不同,需要写不同的方法

//准备一个类。
    public class CommonMethod
    {

        public static void showInt(int parameter)
        {
            Console.WriteLine("This is {0}, paramter={1}, type = {2}",
            typeof(CommonMethod).Name, parameter.GetType().Name, parameter
            );
        }



        public static void showString(string parameter)
        {
            Console.WriteLine("This is {0}, paramter={1}, type = {2}",
            typeof(CommonMethod).Name, parameter.GetType().Name, parameter
            );

        }


        public static void showDateTime(DateTime parameter)
        {
            Console.WriteLine("This is {0}, paramter={1}, type = {2}",
            typeof(CommonMethod).Name, parameter.GetType().Name, parameter
            );
        }
    }


//program.cs 中使用。
 CommonMethod.showInt(123);
 CommonMethod.showString("hello world");
 CommonMethod.showDateTime(DateTime.Now); 

运行后效果。 image.png

2. 1.0 时代,不同的类型,要写多个,很麻烦,于是有优化的方法 。

   public class CommonMethod
    {
    
        ...
        public static void showObj(object oParamter)
        {
            Console.WriteLine("showObj:This is {0}, paramter={1}, type = {2}",
           typeof(CommonMethod).Name, oParamter.GetType().Name, oParamter
           );
        }
    }

//program.cs 中使用。

CommonMethod.showObj(123);
CommonMethod.showObj("hello world");
CommonMethod.showObj(DateTime.Now);

运行后效果。 image.png

3 使用泛型写法。

   public class CommonMethod
    {
    
        ...
        public static void show<T>(T t)
        {
            Console.WriteLine("show:This is {0}, paramter={1}, type = {2}",
               typeof(CommonMethod).Name, t.GetType().Name, t
             );
        }

    }
    //program.cs 中使用。

    CommonMethod.show(123);
    CommonMethod.show("hello world");
    CommonMethod.show(DateTime.Now);

运行后效果。 image.png

简单的说, 使用泛型 让你写与任何数据类型一起工作的类与方法 。

  • 2.0 推出的新语法。 声明的时候不指定,调用的时候指定。
  • 是一种延迟声明: 把参数类型的声明推迟到调用。
  • 不是语法糖,是由框架升级提供的功能 (编译器支持 编译时为占位符 +jit)。

典型的应用

  List<int>
  List<string>

二 范型和使用 obj 的区别, object 装箱拆箱。

装箱的例子。

  int val = 100;
  object obj = val;  //装箱
  Console.WriteLine ("对象的值 = {0}", obj); //对象的值 = 100

拆箱的例子。

  int val = 100;
  object obj = val;  
  int num = (int) obj;   //拆箱。
  Console.WriteLine ("num: {0}", num); //num: 100

内部操作。 int,string 类型 内存分配的是栈, 引用类型,使用堆 (托管堆)

image.png

image.png

C#中对装箱和拆箱都是隐式的,根本的方法是对代码进行分析,而分析最直接的方式是了解原理结何查看反编译的IL代码。比如:在循环体中可能存在多余的装箱,你可以简单采用提前装箱方式进行优化

三 范型类,接口,委托。 (一个类满足不同的具体类型,做相同的事)

3.1 类,接口,委托的泛型写法。


    public class GenericClass<T>
    {
        public T _t;

    }

    public interface IGeneric<T>
    {
        T GetT(T t);
    }

    public delegate void SayHi<T>(T t); //范型委托

   //使用时,需指定具体类型。

3.2 范型约束

范型约束。 设好where 后, 传进来的t 只能是 指定类型的
    public class Constraint
    ...
       public static void show<T>(T param) where T : People
       {
           Console.WriteLine($" id = {param.Id}, name =  {param.Name}");
       }

//program.cs 中使用。
   People p = new People()
   {
       Id= 110,
       Name = "p2"
   };

   People p2 = new People()
   {
       Id= 111,
       Name = "p2"
   };


   Constraint.show(p);
   Constraint.show(p2);

  //注意细节 ,where 不能用sealed 类

image.png

3.3 协变。(不用甚解)

起因是一种写法不支持。

image.png 明明是同一个东西,但不允许写。

 //使用如下方法就可以了。  out  (只能做为返回值)  定义接口时,有更宽的适用面,工作中几乎不用到。
   IEnumerable<Bird> birdList1 = new List<Bird>();
   IEnumerable<Bird> birdList2 = new List<Sparrow>();

3.4 范型缓存。

一个类型会有一个缓存。


   public class GenericCache<T>
   {
       static GenericCache()
       {
           Console.WriteLine(" this is static GenericCache");

           _Typetime = string.Format("{0} _ {1}", typeof(T).FullName, DateTime.Now.ToString());
       }


       private static string _Typetime = "";

       public static void GetCache()
       {
           Console.WriteLine($"GetCache{_Typetime}");
          // return _Typetime;
       }
       
         Console.WriteLine("*******generic cache start******************");
   GenericCache<int>.GetCache();
   GenericCache<string>.GetCache();
   GenericCache<int>.GetCache();

   Console.WriteLine("*******generic end******************");

第二次 GenericCache<int> 时构造函数就没有跑 image.png