Framework类库中的泛型

泛型可以使代码重用,提高开发效率

CLR允许在引用类型、值类型或接口中定义泛型方法;

CLR允许创建泛型引用类型、泛型值类型(枚举不允许创建)、泛型委托类型和泛型接口类型;

System.Collections.Generics中定义了List<T>,<T>表示它操作的是一个未指定数据类型;定义泛型类型或方法时,T是一个变量名,在源代码中能够使用一个数据类型的任何位置都能用T,例如方法参数、返回值等等。

泛型参数变量要么称为T,要么以T开头(如Tkey,TEvent...)

定义好泛型类型后,使用泛型类型或方法时,制定具体的类型实参

var validationResult = new List<ValidationResult>();

泛型的优势

  • 源代码保护

    使用泛型算法时候,不需要了解算法内部的具体实现
  • 类型安全

    将泛型算法运用于一个具体的类型,只有与数据类型兼容算法的对象才能使用算法,若不兼容,便会编译错误或运行异常
  • 更加清晰的代码

    由于编译器强制类型安全,减少了代码中的转型次数
  • 更佳的性能

    由于装箱会造成性能的浪费,通过泛型避免了装箱

下面是一段泛型与非泛型的算法性能测试对比

    class Program
    {
        static void Main(string[] args)
        {
            ValueTypePreTest();
            ReferenceTypePreTest();
            Console.ReadKey();
        }

        private static void ValueTypePreTest()
        {
            const int count = 10000000;
            using (new OperationTimer("List<Int32>"))
            {
                List<int> l = new List<int>();
                for (int i = 0; i < count; i++)
                {
                    l.Add(i);
                    int x = l[i];
                }
                l = null;//确保进行垃圾回收
            }

            using (new OperationTimer("ArraryList of Int32"))
            {
                ArrayList arr = new ArrayList();
                for (int i = 0; i < count; i++)
                {
                    arr.Add(i);
                    int x = (int)arr[i];
                }
                arr = null;
            }
        }

        private static void ReferenceTypePreTest()
        {
            const int count = 10000000;
            using (new OperationTimer("List<String>"))
            {
                List<string> l = new List<string>();
                for (int i = 0; i < count; i++)
                {
                    l.Add("X");
                    string x = l[i];
                }
                l = null;//确保进行垃圾回收
            }

            using (new OperationTimer("ArraryList of String"))
            {
                ArrayList arr = new ArrayList();
                for (int i = 0; i < count; i++)
                {
                    arr.Add("X");
                    string x = (string)arr[i];
                }
                arr = null;
            }
        }

    }

    class OperationTimer : IDisposable
    {
        private long _start;
        private string _text;
        private int _collectionCount;

        public OperationTimer(string text)
        {
            _text = text;
            _collectionCount = GC.CollectionCount(0);
            _start = Stopwatch.GetTimestamp();
        }

        public static void PreparForPeration()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
        }

        public void Dispose()
        {
            Console.WriteLine("{0,6:###.00} seconds(GCs={1,3}) {2}",
                (Stopwatch.GetTimestamp() - _start) / (double)Stopwatch.Frequency,
                GC.CollectionCount(0) - _collectionCount,
                _text
                );
        }
    }

Wintellect的Power Collections库

Wintellect公司开发的一些C++集合类库

http://www.wintellect.com/dotnet-software-development

泛型基础结构

开放类型和封闭类型

具有泛型类型参数的类型称为开放类型(例如:Directory<,>),CLR禁止构造开放类型的任何实例

代码引用一个泛型类型时,可指定一组泛型类型实参,假如为所有类型实参传递都是实际数据类型,称为封闭类型(例如:List<string>

开放类型和封闭类型

具有泛型类型参数的类型称为开放类型(例如:Directory<,>),CLR禁止构造开放类型的任何实例

代码引用一个泛型类型时,可指定一组泛型类型实参,假如为所有类型实参传递都是实际数据类型,称为封闭类型(例如:List<string>

泛型类型和继承

泛型类型任然是一种类型,它可以从其他类型派生。

泛型类型的同一性

不要为了简化代码而定义一个新的类型继承泛型,这样会散失同一性和相等性,可以通过下面的方式简化代码输入

using DateTimeList=System.Collections.Generic.List<DateTime>;

代码爆炸

CLR 优化了泛型类型的编译代码,避免了每次都要为不同的泛型类型生成对应的代码

泛型接口

通过泛型接口避免值类型发生装箱

   public interface IEnumerator<T>:IDisposable,IEnumerator
   {
       T Current{get;}
   }

泛型委托

保证任何类型的对象都能以一种类型安全的方式传给回调方法;而且泛型委托也是为了避免一个值类型实例在传递给回调方法时不再发生装箱

委托和接口的协变和逆变泛型类型实参

http://www.cnblogs.com/liunlls/p/inout.html

泛型方法

泛型除了可以定义类型的参数,还可以为方法定义一个只作用域于方法的类型参数

泛型的类型推断

        public static void Display<T>(T input){
            System.Console.WriteLine(input);
        }
        Display(123);
        Display("aaa")

泛型和其他成员

在C#中,属性、事件、索引器、构造函数等成员是不能有类型参数的,但是在泛型类型中,这些成员的代码是可以使用类型参数的;

C#不允许他们指定自己的泛型类型参数,C#团队认为开发人员很少需要将这些成员作为泛型使用,当然为这些成员添加泛型代价也很高

可验证性和约束

http://www.cnblogs.com/liunlls/p/Generics.html

泛型(Generics)的更多相关文章

  1. [19/03/23-星期六] 容器_ 泛型Generics

    一.概念 生活中的容器不难理解,是用来容纳物体的,程序中的“容器”也有类似的功能,就是用来容纳和管理数据. 数组就是一种容器,可以在其中放置对象或基本类型数据. ---优势:是一种简单的线性序列,可以 ...

  2. Java 泛型(Generics)

    Generics, 类似C++中的模版. 允许在定义类和接口的时候使用类型参数(type parameters), 声明的类型参数在使用的时候用具体的类型来替换. 如 ArrayList<Str ...

  3. Java 泛型(Generics) 综述

    一. 引子 一般的类和方法.仅仅能使用详细类型:要么是基本类型.要么是自己定义类型.假设要编写能够应用于多种类型的代码,这样的刻板的限制对代码的束缚就会非常大. 多态算是一种泛化机制,但对代码的约束还 ...

  4. Welcome-to-Swift-22泛型(Generics)

    泛型代码可以确保你写出灵活的,可重用的函数和定义出任何你所确定好的需求的类型.你可以写出避免重复的代码,并且用一种清晰的,抽象的方式表达出来. 泛型是Swift许多强大特征中的其中一个,许多Swift ...

  5. [JavaCore]JAVA中的泛型

    JAVA中的泛型 [更新总结] 泛型就是定义在类里面的一个类型,这个类型在编写类的时候是不确定的,而在初始化对象时,必须确定该类型:这个类型可以在一个在里定义多个:在一旦使用某种类型,在类方法中,那么 ...

  6. Java1.5泛型指南中文版(Java1.5 Generic Tutorial)

    Java1.5泛型指南中文版(Java1.5 Generic Tutorial) 英文版pdf下载链接:http://java.sun.com/j2se/1.5/pdf/generics-tutori ...

  7. java泛型小问题

    几年前当Java5还未正式发布的时候,看到过一些人写的介绍Tiger中的新特性,当时对我第一感觉冲击最大的就是泛型(generics)和注释(annotation),因为它们直接影响了我们编码的语法习 ...

  8. 泛型-----键值对----映射 hashmap--entry中key value 链表

    connection map 集合框架 * java.util.Collection *集合与数组相似,也是可以保存一组元素,并且提供了操作元素的相关方法. *collection是所有集合的顶级接口 ...

  9. Java下的框架编程(反射,泛型,元数据,CGLib,代码动态生成,AOP,动态语言嵌入)

    Java 虽然没有动态语言般暴起,但仍然天连天,水接水的生出好多框架技术---反射(reflection),泛型(generics),元数据(annotation),proxies(proxy/cgl ...

随机推荐

  1. ASP.NET Core Linux下为 dotnet 创建守护进程(必备知识)

    前言 在上篇文章中介绍了如何在 Docker 容器中部署我们的 asp.net core 应用程序,本篇主要是怎么样为我们在 Linux 或者 macOs 中部署的 dotnet 程序创建一个守护进程 ...

  2. 使用Gemini构建自己的IDE

    你的项目中的领域特定语言是否需要自己的IDE?Visual Studio Shell是选择之一,但是过于庞大不易部署,而且很难使用.Tim Jones的Gemini框架是一个轻量级替代方案. Gemi ...

  3. Linux2 在Linux(CentOS)上配置SSH免登陆

    前言:      本文主要是我在安装hadoop之前,需要先配置SSH免登陆.通过网上搜索,发现不少类似的资料,但多少都有些小问题,所以结合自己的实践,记录在此,作为参考.如果能帮助到其他人,自然是更 ...

  4. 【整理】待毕业.Net码农就业求职储备

    声明:本文题目来源于互联网,仅供即将从学校毕业的.Net码农(当然,我本人也是菜逼一个)学习之用.当然,学习了这些题目不一定会拿到offer,但是针对就业求职做些针对性的准备也是不错的.此外,除了技术 ...

  5. Java ServletContextListener用法

    ServletContext 被 Servlet 程序用来与 Web 容器通信.例如写日志,转发请求.每一个 Web 应用程序含有一个Context,被Web应用内的各个程序共享.因为Context可 ...

  6. Docker实践:运行Python应用

    本文将使用fig应用编排实现一个python的计数器,并使用web展示. 阅读本文您需要具备以下知识: 1.了解Python 2.熟练Docker基础知识(包括Dockerfile语法) 3.了解Do ...

  7. 负载均衡session会话保持方法

    负载均衡时,为了保证同一用户session会被分配到同一台服务器上,可以使用以下方法:1.使用cookie将用户的session存入cookie里,当用户分配到不同的服务器时,先判断服务器是否存在该用 ...

  8. JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式

    相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...

  9. KnockoutJS 3.X API 第六章 组件(5) 高级应用组件加载器

    无论何时使用组件绑定或自定义元素注入组件,Knockout都将使用一个或多个组件装载器获取该组件的模板和视图模型. 组件加载器的任务是异步提供任何给定组件名称的模板/视图模型对. 本节目录 默认组件加 ...

  10. 使用 fixed role 授予权限

    今天下午,Leader 发mail给我,要求授予某个User对数据库只读的权限. Step1,在SQL Server中为该用户创建一个Login和User,在创建User时,建立Login 和 Use ...