美文网首页.Net基础系列
泛型程序设计详解(一)

泛型程序设计详解(一)

作者: 小世界的野孩子 | 来源:发表于2019-08-07 17:22 被阅读0次

前言

泛型是C#和.Net的一个重要概念,泛型不仅是C#编程语言中的一部分,而且与程序集中的IL(Intermediate Language)代码紧密的集成。

在平时编程过程中,常常会出现编写一些差不多的代码块,不同的仅是处理不同的数据类型。比如一个处理int数据的方法,现在新加了string类型的数据。是不是把之前的方法复制一遍,然后修改类型int为string。当然这样的方法是没有错的,那么后面又新增了其他的许多类型怎么办?还是复制修改吗?这样代码看上去很冗余,很复杂。这时候泛型就出现了。下面我们看下为何使用泛型吧。

优点

下面介绍下泛型的优点,尤其是下面几个:

  • l 性能
  • l 类型安全
  • l 二进制代码重用

一、性能

    泛型的一个主要优点就是性能,在泛型集合类和非泛型集合类中,对值类型使用非泛型集合类,在把值类型转换为引用类型和把引用类型转换为值类型的时候,需要进行装箱和拆箱的操作(前面的文章中讲到了拆箱和装箱会造成一定的性能损失),当集合数据量大的时候造成的性能损失也就随之的增大了。

使用非泛型集合时:

 var list = new ArrayList();
            list.Add(100);//装箱  int-object
            int i = (int)list[0];//拆箱  object-int
            foreach (int item in list)
            {
                Console.WriteLine(item);//遍历拆箱输出
            } 

使用泛型集合类时:

var list = new List<int>();
            list.Add(100);//无装箱操作 
            int i =  list[0];//无拆箱拆箱 
            foreach (int item in list)
            {
                Console.WriteLine(item);//无拆箱操作
            } 

减少装箱拆箱操作,节省了性能消耗。这也就是泛型的主要优点了。

二、类型安全

泛型另一个优点就是类型安全,这里我们还是使用非泛型集合类ArrayList()和泛型集合类List<T>来做案例。

非泛型集合类ArrayList():

 var list = new ArrayList();
            list.Add(100);// 添加一个int类型
            list.Add("string");//添加一个string类型
            foreach (int item in list)
            {
                Console.WriteLine(item);//遍历循环输出
 }

这里允许输出和抛出异常:

System.InvalidCastException:“Unable to cast object of type 'System.String' to type 'System.Int32'.” 

无法强制把”string”转换成int类型。

我们再看泛型集合类:

            list.Add(100);// 添加一个int类型 list.Add("string");//添加一个string类型,编译器报错,无法从string转换到int
            foreach (int item in list)
            {
                Console.WriteLine(item);//遍历循环输出 }

在添加”string”类型的时候编译器报错,无法添加。这里也就杜绝了后续的错误。这也就是保证了类型的安全。

三、二进制代码重用

泛型允许更好的重用二进制代码,泛型类型可以定义一次,并且可以再许多不同的类型实例化,相比C++来说,不用每次访问源代码。

例如上面使用的泛型集合类,using System.Collections.Generic; 中的List<T>类,可以用int,string,自定义类去实例化。

泛型类型还可以在一种语言定义,然后再其他任何.Net语言中使用。

泛型类的功能

这里我们可以来了解下创建泛型类了之后,泛型类有哪些功能呢?

  • l 默认值
  • l 约束
  • l 继承
  • l 静态成员

一、默认值

在我们定义了泛型类型之后如何赋值呢?

public class Tclass<T> { public static T Get()
        {
            T a = default; return a;
        }

    }

因为在泛型中初始给值不好给,你说给null吧,null是给引用类型的,你是给0吧,这又是给值类型的,这时候出现了default,当时引用类型调用时就给null,当时值类型时就0。

二、约束

说到泛型类型的约束时,不得不提关键字where,where是用来限制参数的范围的,如果不符合where条件指定的参数范围,编译是不允许通过的。

这里泛型类型的约束主要可以分为以下6中

  • l Where T: class(类型参数必须是引用类型)
  • l Where T:struct(类型参数必须是值类型)
 public class Tclass<T,U>
        where T:class //类型参数为引用类型
        where U:struct  //类型参数为值类型
             {} 
    • l Where T:<接口名称>(类型参数必须是指定的接口或者实现指定的接口)
/// <summary>
    /// 接口 /// </summary>
    interface Itest
    {
    } /// <summary>
    /// 定义一个字典类型 /// </summary>
    /// <typeparam name="TK"></typeparam>
    /// <typeparam name="TV"></typeparam>
    class Dictionary<TK, TV>
      where TK : IComparable, IEnumerable where TV : Itest
    { public void Add(TK key, TV val)
        {
        }
    }
    • l Where T:<基类名>(参数必须是指定的基类或者是派生自指定的基类)
class Ttest { } class Tclass<T> where T:Ttest
    {

    }
    • l Where T:new ()(这是一个构造函数的约束,指定参数类型必须有一个默认构造函数,当与其他约束一起使用时必须放在其最后)
  class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
  {
      // ... }
    • l Where T1:T2(这个约束指定类型T1派生自泛型类型T2,也就是说T1的参数类型要和T2一样)

<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">  public class Tclass<T> where T:IComparable { }</pre>

三、继承

泛型类型的继承与普通类的继承相似但不同。

 /// <summary>
    /// 抽象基类,泛型类型 /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class Ttest<T> { public abstract T Add(T x, T y);
    } /// <summary>
   /// 继承抽象基类,实现int类型 /// </summary>
   /// <typeparam name="T"></typeparam>
    class Tclass<T> : Ttest<int> { public override int Add(int x, int y) => x + y;  

    }

四、静态成员

泛型类型的静态成员需要特殊的关注,泛型类的静态成员只能在类的一个实例中共享。

 /// <summary>
    /// 泛型类型,静态字段x /// </summary>
    /// <typeparam name="T"></typeparam>
    public class Ttest<T> { public static int x;
    } class Program
    { static void Main(string[] args)
        {
            Ttest<string>.x = 111;
            Ttest<int>.x = 222;
            Console.WriteLine(Ttest<string>.x);
        }

    }

上面事例中最后输出的为111,

总结

这里我们主要是介绍了泛型的优点及泛型类型的功能。在我们日常的编程中会发现很多地方可以使用泛型。提高代码的扩展性及重用性。同时也可以减少对object类型的使用,采用泛型类型的使用来替代。较少对性能的消耗。我们下一节主要是对泛型类型的协变及抗变进行一定的理解。


只要认为是对的就去做,坚持去做,不要在乎别人的看法,哪怕是错,至少你有去做过证明曾经你努力过。

相关文章

  • 泛型程序设计

    诚心推荐这一篇文章更好 java 泛型详解 泛型程序设计 泛型意味着编写的代码可以被不同类型重用 ArrayLis...

  • Java泛型与Kotlin泛型

    正文 本文主要列举Java泛型与Kotlin泛型的基本知识,以及两者的区别。 什么泛型 泛型程序设计是程序设计的一...

  • 前端深入理解Typescript泛型概念

    首先介绍一下泛型的概念 泛型程序设计(generic programming)是程序设计语言的一种风格或范式。泛型...

  • Rust中的泛型

    [TOC] Rust中的泛型 泛型程序设计是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写...

  • 泛型程序设计详解(一)

    前言 泛型是C#和.Net的一个重要概念,泛型不仅是C#编程语言中的一部分,而且与程序集中的IL(Intermed...

  • 泛型程序设计

    泛型程序设计 为什么要使用泛型程序设计 类型参数使程序具有更好的可读性和安全性 定义简单泛型类 泛型方法 类型变量...

  • 泛型

    Kotlin 泛型详解 声明一个泛型类 声明一个泛型方法 泛型约束 List 和 List 是...

  • C++模板

    C++模板和泛型程序设计 泛型程序设计(generic programming)是一种算法在实现时不指定具体要操作...

  • kotlin-----理解kotlin中的泛型和注解

    一、泛型 泛型是什么? 泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,...

  • java 泛型

    java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一

网友评论

    本文标题:泛型程序设计详解(一)

    本文链接:https://www.haomeiwen.com/subject/ukdadctx.html