泛型的学习

  • 泛型的学习已关闭评论
  • 94 次浏览
  • A+
所属分类:.NET技术
摘要

传统方法使用Object类型我们通过一个例子来体现性能的问题结果为:
1.泛型方法:在方法名称后面多一对尖括号,尖括号中有占位符
2.延迟声明:声明的时候,只是给一个占位符T,T是什么类型?不知道什么类型—调用的时候,指定你是什么,调用的时候,你说什么就是什么;
3.占位符: T —类型参数 — 类型变量
4.类型参数当作方法的参数的时候,明确参数类型。


泛型的学习

一、泛型的引入

  1. 泛型---泛:宽泛的--不确定的; 型:类型---不确定的类型
  2. 无处不在的
  3. 调用普通方法的时候,参数类型在声明的时候就确定了,调用按照类型传递参数即可
    a. 如果有100个类型---100个方法?--很累
    b. 有没有能够做一个方法可以能够满足不同类型的需求呢?

传统方法

   public static   class CommonMethod     {         public static void ShowInt(int Parameter)         {             Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");         }          public static void ShowString(string Parameter)         {             Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");         }          public static void ShowDateTime(DateTime Parameter)         {             Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");         }          } 
  1. Object类型作为参数 ----可以传递不同的参数
    a. 任何子类出现的地址都可以让父类来代替
    b. 万物皆对象---任何一个类型都是继承自Object

使用Object类型

   public static   class CommonMethod     {         public static void ShowObject(object Parameter)         {             Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");         }     } 
  1. 问题
    a. 性能问题 ---装箱拆箱---在c#语法中,按照声明时决定类型的(栈、托管堆)
    b. 类型安全问题

我们通过一个例子来体现性能的问题

public  class PerformanceTest     {         public static void Show()         {             int ivalue = 1234;             //消耗的时间             long commonSecond = 0;             long objectSecond = 0;             long genericSecond = 0;              {                 Stopwatch sw = new Stopwatch();                  sw.Start();                 for (int i = 0; i < 1000_000_000; i++) {                     ShowInt(ivalue);                 }                sw.Stop();                 commonSecond = sw.ElapsedMilliseconds;             }              {                 Stopwatch sw = new Stopwatch();                 sw.Start();                 for (int i = 0; i < 1000_000_000; i++)                 {                     ShowObject(ivalue);                 }                 sw.Stop();                 objectSecond = sw.ElapsedMilliseconds;             }              {                 Stopwatch sw = new Stopwatch();                 sw.Start();                 for (int i = 0; i < 1000_000_000; i++)                 {                     Show(ivalue);                 }                 sw.Stop();                 genericSecond = sw.ElapsedMilliseconds;             }             Console.WriteLine($"commonSecond: {commonSecond} objectSecond: {objectSecond} genericSecond :{genericSecond} ");         }                      private static void ShowInt(int r)         {          }          private static void ShowObject(object o)         {          }            private static void Show<T>(T parameter)         {          }      } 

结果为:
泛型的学习

  1. 有没有既性能好,也能够支持多种类型的方法呢?---泛型方法
    a. 声明多了一对尖括号 + 占位符T
    b. 调用--也需要多一对尖括号,尖括号中指定的类型要和传递的参数的类型一致。
    c. 如果可以参数推到出类型---尖括号可以省略。
  2. 泛型方法---做到了性能高---可以一个方法满足不同类的需求:---又让马儿跑,又让马吃草

二、泛型的声明

1.泛型方法:在方法名称后面多一对尖括号,尖括号中有占位符
2.延迟声明:声明的时候,只是给一个占位符T,T是什么类型?不知道什么类型---调用的时候,指定你是什么,调用的时候,你说什么就是什么;
3.占位符: T ---类型参数 --- 类型变量
4.类型参数当作方法的参数的时候,明确参数类型。

三、泛型的特点+原理 -- 底层如何支持的?

  1. 在高级语言中,定义的泛型T,在计算机执行的时候一定要是一个具体的类型。
  2. 在底层如何支持?---在底层看到,生成的结果是LIST1[T] Dictionary2[TKey,TValue]
  3. 在底层---生成了1、2、3、4、5、6
  4. 编译器必须要能够支持泛型
  5. CLR运行时环境也需要要支持泛型
  6. 泛型当然是框架的升级支持的---泛型不是语法糖---有框架的升级支持的;
  7. 语法糖:是编译器提供的便捷功能。

四、泛型的多种应用

  1. 泛型方法---可以一个方法满足不同类型的需求
  2. 泛型接口---可以一个接口满足不同类型的需求 --- 尖括号+占位符
  3. 泛型类-----可以一个类型满足不同类型的需求
  4. 泛型委托---可以一个委托满足不同类型的需求
    尖括号中可以有多个类型参数。
public class GenericsTest     {         public interface GenericsInterface<T>         {             public T show();         }         public class GenericsClass<T>         {             public void Show(T t)             {                  Console.WriteLine(t);              }         }          public delegate T genericsDelegate<T>();          //1.泛型方法         static void Show<T>(T value)         {             Console.WriteLine(value);         }                  //2.泛型接口         GenericsInterface<string> genericsString = null;         GenericsInterface<DateTime> genericsDatetime = null;                 //3.泛型类         GenericsClass<string> genericsClassString = null;         GenericsClass<DateTime> genericsClassDateTime = null;          //4.泛型委托         genericsDelegate<string> genericsDelegateString=null;         genericsDelegate<DateTime> genericsDelegateDateTime=null;      }  

类型参数一定要为T吗?不一定,也可以是其他的名字(不要使用关键字)。
并且尖括号中可以有多个类型参数

  public class GenericsClass<T,S,X,GODLWL>         {             public void Show(T t)             {                  Console.WriteLine(t);              }         }  

继承抽象泛型类的情况

     //使用T报错,为什么不行?要继承的时候,必须要确定类型,         public abstract class Children:FatherClass<T>         {          }       //不报错,在子类实例化的时候,父类的类型也会被确定。          public class Children1<S> : FatherClass<S>         {          }  

继承类的状况

   public class Children2<S>         {             public S show()             {                 return default(S);              }              public S show(S s)             {                 return s;             }         }  

未完待续