泛型:通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用。
 namespace GenericConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int obj = 3;
            Test<int> t= new Test<int>(obj);
            Console.WriteLine("int:"+t.obj.ToString());
            string obj2 = "helloworld";
            Test<string> t2= new Test<string>(obj2);
            Console.WriteLine("string:" + t2.obj.ToString());
        }
    }

/// <summary>
    /// Test是一个范型类
    /// T是要实例化的范型类型
    /// 如果T被实例化为int类型,那么成员变量obj就是int类型
    /// 如果T被实例化为string类型,那么成员变量obj就是string类型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    class Test<T>
    {
        public T obj;
        public Test(T obj)
        {
            this.obj = obj;
        }
    }
}

C#
泛型机制:C#泛型能力有CLR在运行时支持:C#泛型代码在编译为IL代码和元数据时,采用特殊的占位符来表示范型类型,并用专有的IL指令支持泛型操作。而真正的泛型实例化工作以“on-demand”的方式,发生在JIT编译时。
    1、第一轮编译时,编译器只为Test<T>类型产生“泛型版”的IL代码与元数据——并不进行泛型的实例化,T在中间只充当占位符。例如:Test类型元数据中显示
       的<!T>
    2、JIT编译时,当JIT编译器第一次遇到Test<int>时,将用int替换“范型版”IL代码与元数据中的T——进行泛型类型的实例化。例如:Main函数中显示的
       <int>   
    3、CLR为所有类型参数为“引用类型”的泛型类型产生同一份代码;但是如果类型参数为“值类型”,对每一个不同的“值类型”,CLR将为其产生一份独立的代
       码。因为实例化一个引用类型的泛型,它在内存中分配的大小是一样的,但是当实例化一个值类型的时候,在内存中分配的大小是不一样的。

C#泛型特点:

1、如果实例化泛型类型的参数相同,那么JIT编辑器会重复使用该类型,因此C#的动态泛型能力避免了C++静态模板可能导致的代码膨胀的问题。

2、C#泛型类型携带有丰富的元数据,因此C#的泛型类型可以应用于强大的反射技术。

3、C#的泛型采用“基类、接口、构造器,值类型/引用类型”的约束方式来实现对类型参数的“显示约束”,提高了类型安全的同时,也丧失了C++模板基于“签
       名”的隐式约束所具有的高灵活性

C#泛型继承:

C#除了可以单独声明泛型类型(包括类与结构)外,也可以在基类中包含泛型类型的声明。但基类如果是泛型类,它的类型要么以实例化,要么来源于子类(同样是泛型类型)声明的类型参数,看如下类型

class C<U,V>

class D:C<string,int>

class E<U,V>:C<U,V>

class F<U,V>:C<string,int>

class G:C<U,V> //非法

E类型为C类型提供了U、V,也就是上面说的来源于子类

F类型继承于C<string,int>,个人认为可以看成F继承一个非泛型的类

G类型为非法的,因为G类型不是泛型,C是泛型,G无法给C提供泛型的实例化

泛型类型的成员:

泛型类型的成员可以使用泛型类型声明中的类型参数。但类型参数如果没有任何约束,则只能在该类型上使用从System.Object继承的公有成员

泛型接口:

泛型接口的类型参数要么已实例化,要么来源于实现类声明的类型参数

泛型委托:

泛型委托支持在委托返回值和参数上应用参数类型,这些参数类型同样可以附带合法的约束

delegate bool MyDelegate<T>(T value);

class MyClass

{

static bool F(int i){...}

static bool G(string s){...}

static void Main()

{

MyDelegate<string> p2 = G;

MyDelegate<int> p1 = new MyDelegate<int>(F);

}

}

泛型方法:

1、C#泛型机制只支持“在方法声明上包含类型参数”——即泛型方法。

2、C#泛型机制不支持在除方法外的其他成员(包括属性、事件、索引器、构造器、析构器)的声明上包含类型参数,但这些成员本身可以包含在泛型类型中,
      并使用泛型类型的类型参数。

3、泛型方法既可以包含在泛型类型中,也可以包含在非泛型类型中。

泛型方法声明:如下

public static int FunctionName<T>(T value){...}

泛型方法的重载:

public void Function1<T>(T a);

public void Function1<U>(U a);

这样是不能构成泛型方法的重载。因为编译器无法确定泛型类型T和U是否不同,也就无法确定这两个方法是否不同

public void Function1<T>(int x);

public void Function1(int x);

这样可以构成重载

public void Function1<T>(T t) where T:A;

public void Function1<T>(T t) where T:B;

这样不能构成泛型方法的重载。因为编译器无法确定约束条件中的A和B是否不同,也就无法确定这两个方法是否不同

泛型方法重写:

在重写的过程中,抽象类中的抽象方法的约束是被默认继承的。如下:

abstract class Base

{

public abstract T F<T,U>(T t,U u) where U:T;

public abstract T G<T>(T t) where T:IComparable;

}

class MyClass:Base

{

public override X F<X,Y>(X x,Y y){...}

public override T G<T>(T t) where T:IComparable{}

}

对于MyClass中两个重写的方法来说

F方法是合法的,约束被默认继承

G方法是非法的,指定任何约束都是多余的

泛型约束:

1、  C#泛型要求对“所有泛型类型或泛型方法的类型参数”的任何假定,都要基于“显式的约束”,以维护C#所要求的类型安全。

2、“显式约束”由where子句表达,可以指定“基类约束”,“接口约束”,“构造器约束”,“值类型/引用类型约束”共四种约束。

3、“显式约束”并非必须,如果没有指定“显式约束”,范型类型参数将只能访问System.Object类型中的公有方法。例如:在开始的例子中,
        定义的那个obj成员变量。比如我们在开始的那个例子中加入一个Test1类,在它当中定义两个公共方法Func1、Func2

下面就开始分析这些约束:

基类约束:

class A

{

public void Func1()

{ }

}

class B

{

public void Func2()

{ }

}

class C<S, T>

where S : A

where T : B

{

public C(S s,T t)

{

//S的变量可以调用Func1方法

s.Func1();

//T的变量可以调用Func2方法

t.Func2();

}

}

接口约束:

interface IA<T>

{

T Func1();

}

interface IB

{

void Func2();

}

interface IC<T>

{

T Func3();

}

class MyClass<T, V>

where T : IA<T>

where V : IB, IC<V>

{

public MyClass(T t,V v)

{

//T的对象可以调用Func1

t.Func1();

//V的对象可以调用Func2和Func3

v.Func2();

v.Func3();

}

}

构造器约束:

class A

{

public A()

{ }

}

class B

{

public B(int i)

{ }

}

class C<T> where T : new()

{

T t;

public C()

{

t = new T();

}

}

class D

{

public void Func()

{

C<A> c = new C<A>();

C<B> d = new C<B>();

}

}

d对象在编译时报错:The type B must have a public parameterless constructor in order to use it as parameter 'T' in the generic type or method C<T>

    注意:C#现在只支持无参的构造器约束

此时由于我们为B类型写入了一个有参构造器,使得系统不会再为B自动创建一个无参的构造器,但是如果我们将B类型中加一个无参构造器,那么对象d的实例化就不会报错了。B类型定义如下:

class B

{

public B()

{ }

public B(int i)

{ }

}

值类型/引用类型:

public struct A { }

public class B { }

public class C<T> where T : struct

{

}

C<A> c1 = new C<A>();

C<B> c2 = new C<B>();

c2对象在编译时报错:The type 'B' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or methor 'C<T>'

总结:

1、C#的泛型能力由CLR在运行时支持,它既不同于C++在编译时所支持的静态模板,也不同于Java在编译器层面使用“擦拭法”支持的简单的泛型。

2、C#的泛型支持包括类、结构、接口、委托四种泛型类型,以及方法成员。

3、C#的泛型采用“基类,接口,构造器,值类型/引用类型”的约束方式来实现对类型参数的“显式约束”,它不支持C++模板那样的基于签名的隐式约束

转载于:https://www.cnblogs.com/GeneralXU/archive/2008/04/13/1150919.html

范型编程系列二(非原创)相关推荐

  1. c#范型编程系列一(非原创)

         我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法处理每个数据类型,因为方 ...

  2. C++ Primer 第十六章 模板与范型编程

    16.1 模板定义     模板和c#范型一样,建立一个通用的类或函数,其参数类型和返回类型不具体指定,用一个虚拟的类型来代表,通过模板化函数或类实现代码在的重用.     定义语法是:    tem ...

  3. J2SE5.0新特性之范型编程

    J2SE5.0新特性之范型编程 晁岳攀 smallnest@163.com 本章主要参考sun公司文档. C++程序员对范型编程肯定不陌生,尤其在STL大行其道的时候,C#2.0也将实现范型编程的功能 ...

  4. Javascript模块化编程系列二: 模块化的标准化(CommonJS AMD)

    前言 Javascript模块化编程系列一: 模块化的驱动 在前一篇介绍了为什么要进行Javascript模块化编程.至于如何实现模块化,不同的开发组织和个人具体的实现方式肯定是不一样.如何统一一个规 ...

  5. STM32 C++编程系列二:STM32 C++代码封装初探

    一.STM32与面向对象编程 上一章中提到了,C++的核心之一就在于面向对象思想.相比C语言常用的面向过程编程,面向对象编程的优势在于继承.封装.多态的特性,利用这种思想更有助于我们的程序实现模块化. ...

  6. java原子操作cas_java并发编程系列二:原子操作/CAS

    什么是原子操作 不可被中断的一个或者一系列操作 实现原子操作的方式 Java可以通过锁和循环CAS的方式实现原子操作 CAS( Compare And Swap )  为什么要有CAS? Compar ...

  7. Java 语义网编程系列二: 本体

    什么叫本体 OWL本体用于对领域知识进行建模,本体是语义web的核心元素. 本体元素概述 在web上本体一般以文档的形式进行存储.文档构成如下: A. 本体首部: 首部是一种用来描述本体自身的资源.首 ...

  8. 【note】编程范式(编程范型)的含义和种类,多范式编程语言

    范型 / 范式 = 模式.方法 编程范式 / 编程范型 = 编程的模式.风格 编程范式主要包括:结构化编程.面向对象编程.过程式(程序式)编程.函数式编程(泛函编程).指令式(命令式)编程.泛型编程. ...

  9. 学习ASP.NET Core Razor 编程系列六——数据库初始化

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二--添加一个实体 学习ASP.NET ...

  10. Objective C范型

    范型 范型编程是一种程序语言设计范式,它允许程序员在使用强类型的语言编写代码的时候,延迟确定具体的类型. 以Swift代码为例,假如有一个需求是要交换两个int,很容易写出类似代码 func swap ...

最新文章

  1. Java多线程实现异步调用
  2. linux上mongodb的安装与卸载
  3. 刷前端面经笔记(二)
  4. 本科、硕士、博士的区别
  5. 读取GY-951模块数据(Linux)
  6. 视频封装格式篇(TS)
  7. 安卓系统 国内谷歌服务器,在国内使用搭载安卓原生态系统谷歌手机,会是一种什么体验?...
  8. 团队管理14--盘点团队
  9. win7系统ie被篡改怎么解决
  10. Codeforces 553A Kyoya and Colored Balls 给球涂颜色
  11. C语言数字图像处理---2.3图像空域滤波
  12. 135微信编辑器html模式,135微信编辑器官网【设置思路】
  13. css3彩色3D文字上下漂浮动画js特效
  14. Python 与 Excel 终于互通了 !
  15. Stack Overflow 宣布推出离线版本
  16. 2017百度之星初赛B场总结
  17. android 中篇 文章推荐
  18. [golang]-golang将中文转化为拼音
  19. 站长利好,迅雷宣布开放“迅雷下载JS-SDK”
  20. 传奇GOM引擎版本架设

热门文章

  1. 【Pytorch】Pytorch常见的坑汇总
  2. 【知识图谱】史上最全《知识图谱》2020综述论文,18位作者, 130页pdf
  3. 2019: 属于BERT预训练语言模型之年
  4. 【图神经网络】从源头探讨 GCN 的行文思路
  5. BERT源码分析(一)
  6. matplotlib—patches.Circle
  7. 深度学习5-模型的保存与加载
  8. Pytorch损失函数BCELoss,BCEWithLogitsLoss
  9. Python中的几个重要函数
  10. Bert模型冻结指定参数