C#泛型演示说明:此文章来源于: http://blog.csdn.net/shoutor/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Stack<T>
    {
        private T[] store;
        private int size;
        public Stack()
        {
            store = new T[20];
            size = 0;
        }

        public void Push(T x)
        {
            store[size++] = x;
        }
      
    }
    public class Finder
    {
        // 泛型方法的声明
    public static int Find<T>(T[] items, T item)
   {
       for(int i=0;i<items.Length;i++)
       {
            if(items[i].Equals(item))
           {
               return i;
           }
       }
       return -1;
   }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //泛型方法的调用
            int i = Finder.Find<int>(new int[] { 1, 3, 4, 5, 6, 8, 9 },6);

            Stack<int> x = new Stack<int>();
            x.Push(5);
            Stack<double> y = new Stack<double>();
            y.Push(5.0);
            y.Push(6.0);
        }
    }

}

泛型简介

所谓泛型:即通过参数化类型来实现在同一份代码上操作多种数据类型。泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。

C#泛型赋予了代码更强的类型安全,更好的复用,更高的效率,更清晰的约束。

C#泛型机制简介

C#泛型能力由CLR在运行时支持,区别于C++的编译时模板机制,和java的编译时的“搽拭法”。这使得泛型能力可以在各个支持CLR的语言之间进行无缝的互操作。

C#泛型代码在被编译为IL和元数据时,采用特殊的占位符来表示泛型类型,并用专有的IL指令支持泛型操作。而真正的泛型实例化工作以“on-demand”的方式,发生在JIT编译时。

C#泛型编译机制

第一轮编译时,编译器只为Stack<T>类型产生“泛型版”的IL代码和元数据,并不进行泛型类型的实例化,T在中间只充当占位符。

JIT编译时,当JIT编译器第一次遇到Stack<int>时,将用int类型替换“泛型版”IL代码与元数据中的T -- 进行泛型类型的实例化。

CLR为所有类型参数为“引用类型”的泛型类型产生同一份代码,但如果类型参数为“值类型”,对每一个不同的“值类型”,CLR将为其产生一份独立的代码。

C#泛型的几个特点

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

C#泛型类型携带有丰富的元数据,因此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>{} //非法

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

泛型类型的成员

class C<V>
{
   public V f1; //声明字段
   public D<V> f2; //作为其他泛型类型 的参数
   public C<V x>
   {
      this.f1 = x;
   }
}

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

泛型接口

interface IList<T>
{
   T[] GetElements();
}
interface IDictionary<K,V>
{
   void Add(K key,V value);
}
//泛型接口的类型参数要么已实例化
//要么来源于实现类声明的类型参数

class List<T>:IList<T>,IDictionary<int,T>
{
   public T[] GetElements{}
   {
      return null;
   }
   public void Add(int index,T value){}
}

泛型委托

delegate bool Predicate<T>(T value);
class X
{
    static bool F(int i){...}
    static bool G(string s){...}
    static void Main()
    {
         Predicate<string> p2 = G;
         Predicate<int> p1 = new Predicate<int>(F);
    }
}
    泛型委托支持返回值和参数哂纳感应用参数类型,这些参数类型同样可以附带合法的约束。

泛型方法的简介

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

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

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

泛型方法的声明与调用

public class Finder
{
   // 泛型方法的声明
   public static int Find<T>(T[] items,T item)
   {
       for(int i=0;i<items.Length;i++)
       {
            if(items[i].Equals(item)
           {
               return i;
           }
       }
       return -1;
   }
}

// 泛型方法的调用
int i = Finder.Find<int>(new int[]{1,3,4,5,6,8,9},6);

泛型编程

泛型方法的重载

class MyClass
{
   void F1<T>(T[] a,int i); // 不可以构成重载方法
   void F1<U>(U[] a,int i);

void F2<T>(int x); // 可以构成重载方法
   void F2(int x);

void F3<T>(T t) where T : A; // 不可以构成重载方法
   void F3<T>(T t) where T : 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 U : IComparable;
}
class Derived:Base
{
   // 合法的重写,约束被默认继承
   public override X F(X,Y)(X x,Y y){}

// 非法的重写,指定任何约束都是多余的
   public override T G<T>(T t) where T : Comparable{}
}

泛型约束简介

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

"显式约束"有where字句表达,可以指定"基类约束","接口约束","构造器约束","值类型/引用类型约束"共四中约束.

"显示约束"并非必须,如果没有指定"显式约束",泛型类型参数将只能访问System.Object类型中的公有方法.

基类约束

class A
{
   public void F1(){}
}
class B
{
   public void F2(){}
}

class C(S,T)
where S:A // S继承自A
where T:B // T继承自B
{
   // 可以在类型为S的变量上调用F1
   // 可以在类型为T的变量上调用F2
}

接口约束

interface IPrintable{coid Print();}
interface IComparable<T>{int CompareTo(T v);}
interface IKeyProvider<T>{T HetKey();}

class Dictionary<K,V>
  where K:IComparable<K>
  where V:IPrintable,IKeyProvider<K>
{
   // 可以在类型为K的变量上调用CompareTo
   // 可以在类型为V的变量上调用Print和GetKey
}

构造器约束

class A
{
   public A(){}
}
class B
{
   public B(int i)()
}

class C<T>
  where T:new()
{
   // 可以在其中使用T t = new T();
}
C<A> c = new C<A>(); // 可以,A有无参数构造器
C<B> c = new C<B>(); // 错误,B没有无参数构造器

值类型/引用类型约束

public struct A{...}
public class B{...}

class C<T>
where T : struct
{
 // T在这里面是一个值类型
}
C<A> c = new C<A>(); // 可以,A是一个值类型
C<B> c = new C<B>(); // 错误,B是一个引用类型

总结

C#的泛型能力有CLR在运行时支持,它既不同于c++在编译时所支持的静态模板,也不同于java在编译器层面使用"檫拭法"支持的简单的类型.

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

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

C# 2.0 泛型编程相关推荐

  1. C# 2.0 泛型编程 选择自 shoutor 的 Blog

    C# 2.0 泛型编程     选择自 shoutor 的 Blog 关键字   C# 2.0 泛型编程 出处   C#泛型演示 class Stack<T> {    private T ...

  2. 【整理】C#2.0泛型编程之概述、default()方法、别名指定与泛型约束

    泛型概述 首先我们看一个在泛型出现之前通用的数据结构示例 通用数据结构类 Code public class Stack {     object[] m_Items;     public Stac ...

  3. sql和泛型方法返回泛型_基于泛型编程的序列化实现方法

    写在前面 序列化是一个转储-恢复的操作过程,即支持将一个对象转储到临时缓冲或者永久文件中和恢复临时缓冲或者永久文件中的内容到一个对象中等操作,其目的是可以在不同的应用程序之间共享和传输数据,以达到跨应 ...

  4. 基于泛型编程的序列化实现方法

    写在前面 序列化是一个转储-恢复的操作过程,即支持将一个对象转储到临时缓冲或者永久文件中和恢复临时缓冲或者永久文件中的内容到一个对象中等操作,其目的是可以在不同的应用程序之间共享和传输数据,以达到跨应 ...

  5. 估算带卷积核二分类0,3的网络的收敛时间和迭代次数

    制作一个网络分类minst的0和3求出这网络的迭代次数曲线表达式n(δ),和准确率表达式p-max(δ),用预期准确率去估算n,并推算需要的时间. 将minst的28*28的图片缩小到9*9,网络用一 ...

  6. C++ 入门导引(这是一篇由GPT4写的文章)

    C++ 应用场景 C++ 是一种广泛应用的编程语言,拥有多种使用场景.以下是 C++ 的一些主要应用场景: ​1. 游戏开发:C++ 常用于游戏开发,尤其是大型 3D 游戏.它可以轻松地与图形 API ...

  7. 关于Delphi通用涵数

    DELPHI程序注册码设计(转载)     思路是这样的:程序运行时先检测注册表,如果找到注册项,则表明已经注册,如果没有找到注册项,则提示要求注册.         <注册例程>     ...

  8. template详解

    1. 函数模板 1. 函数模板定义 关键字:"template开头","参数列表非空" 定义一定要以:template<->开头(为了解释为什么 i ...

  9. 神经网络收敛标准与准确率之间的数学关系

    制作一个带一个3*3卷积核的神经网络,测试集是minst的0和2图片集,将28*28的图片缩小成9*9,隐藏层30个节点所以网络的结构是 S(minst0)-(con3*3)49-30-2-(1,0) ...

最新文章

  1. 计算机管理 未分配磁盘,win7系统硬盘(未分配磁盘)如何重新建立扩展分区?
  2. Bitcoin.com| 比特币现金在澳大利亚的零售支出大幅超过BTC
  3. 使COUNT(*)查询总数变快
  4. 【项目实战】基于随机森林算法的房屋价格预测模型
  5. Serializable:明明就一个空接口!为什么还要实现它?
  6. clickhouse 子查询_Clickhouse 查询分布式表子查询 (Distributed Subqueries )
  7. [XSY] 简单的数论题(数学、构造)
  8. 正则表达式match和group的区别 具有相同模式的字符串使用组的提取案例及原理
  9. C++关键字 friend
  10. 在Oracle的FORM中对不同的状态采取不同的颜色显示
  11. 用三款评测证明,数学思维在线学习APP正在用游戏化打开数学之门
  12. 教你sql查询分析器执行存储过程
  13. SpreadJS 14.1 Crack by Xacker
  14. 常用的软件测试方法及特点分析
  15. 如何玩转私域引流?全链路拆解经典玩法和实战案例
  16. idea配置port
  17. 学医后才知道的小知识...
  18. 微信小程序 自定义控件 数字键盘
  19. 移动硬盘和电脑内置硬盘使用时的区别
  20. 基于medianflow的半自动标注数据程序

热门文章

  1. 服务器MXNET环境配置问题
  2. vanish高速反向代理服务器配置
  3. c语言6行6列元素奇数的个数,C语言任意输入n个整数,分别统计奇数的和.奇数的个数.偶数的和.偶数的个数....
  4. 富士康服务器主板X58维修,富士康X58 Blood Rage主板BIOS预览
  5. python读取 .trs 格式等特殊文本文件
  6. 修改centos网口名称
  7. python在哪下载安装,python软件在哪下载
  8. 罗马音平假字复制_罗马音平假名可复制吊字
  9. 几种梯度下降法比较最小值与鞍点(SGD、Momentum、NAG、Adagrad、Adadelta与Rmsprop)
  10. 求求你!不要在网上乱拷贝代码了