第三章 C# 泛型

当两个模块功能相似,仅仅只是类型不同的时候,你会怎么办呢。请看以下代码:

public class IntClass
        {
            List<int> Intlist = new List<int>();
            public void AddList(int i)
            {
                Intlist.Add(i);
            }
        }
        public void Main()
        {
            IntClass c1 = new IntClass();
            c1.AddList(1);
            c1.AddList(1);
        }

但是当我们想c1.AddList("hello word");要插入一个字符串类型的时候,你会怎么做呢?

二逼程序员会这样做:

public class StringClass
        {
            List<string> Intlist = new List<string>();
            public void AddList(string i)
            {
                Intlist.Add(i);
            }
        }

普通程序员会这样做:

public class ObjClass
        {
            List<object> Intlist = new List<object>();
            public void AddList(object i)
            {
                Intlist.Add(i);
            }
        }

仔细想想,不断装箱拆箱是否效率低下呢,当我们要插入bool,char,datetime.....等等类型的时候,我们需要copy这么多类吗?这时我们就用到了泛型。

1.泛型的声明:

public class Class1<T>
    {
        private List<T> List = new List<T>();
        public List<T> GetList()
        {
            return List;
        }
        public void AddList(T t)
        {
            List.Add(t);
        }
    }

2.泛型的默认值:

T t=defalut(T); 如果T是值类型,则t=0;如果T是引用类型,则t=null.

3.泛型约束:

接口约束:where T:Interface   必须显示的实现接口

基类约束:where T:BaseClass 参数必须为BaseClass或者派生类

类约束:where T:class T必须是引用类型

值类型约束: where T:struct T必须是值类型

构造函数约束: where T:new()  必须有默认的构造函数

泛型类型约束: Where T:T1

4静态成员:

不同类型的泛型可以认为是不同的类。  所有静态成员只能在同类中共享。

public class mm<T>
{
public static string Name{get;set;}
}

mm<int> a,mm<int> b,mm<sting>c       a,b可以共享Name,c不能

5.泛型类中的方法重载
方法的重载在.Net Framework中被大量应用,他要求重载具有不同的签名。在泛型类中,由于通用类型T在类编写时并不确定,所以在重载时有些注意事项,这些事项我们通过以下的例子说明:

public class Node<T, V>

{

public T add(T a, V b)          //第一个add

{

return a;

}

public T add(V a, T b)          //第二个add

{

return b;

}

public int add(int a, int b)    //第三个add

{

return a + b;

}

}

上面的类很明显,如果T和V都传入int的话,三个add方法将具有同样的签名,但这个类仍然能通过编译,是否会引起调用混淆将在这个类实例化和调用add方法时判断。请看下面调用代码:

Node<int, int> node = new Node<int, int>();

object x = node.add(2, 11);

这个Node的实例化引起了三个add具有同样的签名,但却能调用成功,因为他优先匹配了第三个add。但如果删除了第三个add,上面的调用代码则无法编译通过,提示方法产生的混淆,因为运行时无法在第一个add和第二个add之间选择。

Node<string, int> node = new Node<string, int>();

object x = node.add(2, "11");

这两行调用代码可正确编译,因为传入的string和int,使三个add具有不同的签名,当然能找到唯一匹配的add方法。

由以上示例可知,C#的泛型是在实例的方法被调用时检查重载是否产生混淆,而不是在泛型类本身编译时检查。同时还得出一个重要原则:

当一般方法与泛型方法具有相同的签名时,会覆盖泛型方法。

泛型类的方法重写
方法重写(override)的主要问题是方法签名的识别规则,在这一点上他与方法重载一样,请参考泛型类的方法重载。

泛型的使用范围
本文主要是在类中讲述泛型,实际上,泛型还可以用在类方法、接口、结构(struct)、委托等上面使用,使用方法大致相同,就不再讲述。

时间: 2024-11-18 02:51:32

第三章 C# 泛型的相关文章

C# in depth ( 第三章 用泛型实现参数化类型)

3.1 为什么需要泛型 避免了强制转换,使代码更易读易写,也就减少了出bug的几率. 提升了性能 由于编译时做了更多的检查,运行时的检查就可以少做很多. JIT能够聪明地处理值类型,能消除很多情况下的装箱和拆箱处理. 3.2 日常使用的简单泛型 3.2.1通过例子来学习: 泛型字典 class DictionaryDemo { static Dictionary<string,int> CountWords(string text) { Dictionary<string,int>

07.C#泛型的限制和可空类型的简单说明(三章3.5-四章4.1)

自己在写文章的同时,也是在学习,对于书中的语句很多其实没有太好的理解,读一本书,要消化!!!三章都是讲泛型的,最后写一下泛型的限制,对于本章学习的完结,one end,one begin. 看下面的代码 1 public class Teacher 2 { 3 public enum Flag { Chinese, English }; 4 public string Name { get; set; } 5 } 6 7 public class ChineseTeacher : Teacher

第三章 泛型编程风格

第三章 泛型编程风格 Standard Template Library(STL)两种组件构成: 容器(container)(vector.list.set.map...) 操作以上容器的所谓的泛型算法(generic algorithm)(find(), sort(), replace(), merge()...) 序列式容器(sequential container):vector.list 依次维护第一个元素.第二个元算......直到最后一个元素,进行迭代操作(iterate)关联式容器

Android教材 | 第三章 Android界面事件处理(二)—— 杰瑞教育原创教材试读

 编者按 JRedu 杰瑞教育原创系列教材将于年后与大家正式见面.为更好的借鉴读者意见,我们将会陆续地在博客园推出一系列教材试读.我们也热忱的欢迎广大博友与我们互动,提出宝贵意见. 本篇博客将推出教材第三章第二部分的试读(传送门:第一部分),请大家继续提出宝贵意见,我们也将为积极互动的博友,免费提供我们的原创教材以及更多福利,也欢迎大家加入最下方QQ群与我们交流,谢谢大家! 3.5 系统设置事件处理 3.5.1onConfigurationChanged响应事件 在App开发过程中,有时候需要获

当代码遇到数理逻辑——面向对象设计与构造第三章总结

在面向对象课程中的第三章,我尝试了基于JML语言的规格化设计,按照AppRunner中的接口文件实现了Path类和PathContainer, Graph, RailWaySystem迭代类.JML语言是一种规格化语言,完全建立于数理逻辑上,既能够为开发者实现类与方法时提供准确的功能参考,也能够在特定工具支持下充当assert的功能和辅助自动生成测试样例. 本篇博客将从以下几方面对第三章进行总结: JML的基本语法与工具链 基于JmlUnitNg的自动测试方法尝试 三次作业架构 程序Bug分析

构建之法前三章读后感

一. 软件作为一个产品,在提供用户使用前经历了许多工序,我们用工程的方式将开发软件的工序,过程加以工程化,系统化.成立了一套完整的体系后,有利于帮助我们开发软件,乃至于大型的系统. 软件具有一定的特殊性,使得软件工程师们做开发提升了一定的难度,但软件工程有助于软件系统的开发,帮助工程师们设计,构建,测试和维护软件.所以,软件工程的最终目的是帮助工程师们创造“足够好”的软件,提高软件的质量,用户满意度,可靠性,可维护性等. 第一章问题:怎么才算是一个真正的软件工程师? 二.   一个优秀的软件,通

0320 《构建之法》前三章观后感

第一章.为我们解释什么是软件,什么是软件工程,读完这章对这些概念有一定的认识这章让我明白,代码不能盲目的敲,好的软件并非两三天,并非一两个人就能赶出来的,需要大家的精诚合作.同时,在编写程序之前,还需要做一系列的分析.设计,要满足客户的需求,后续还要对软件进行测试.维护等.在这之前,我一直觉得能把程序运行,能有正确的结果,那就完成任务了,可这只是整个软件流程的一部分而已.看了邹老师的书,才知道其实创新有很多的方面,除了技术,还有商业思路,差异化等等,这些都给了我很大的感触,作为一名程序员,我们不

家庭作业——第三章

第三章家庭作业    3.69和3.70 3.69 A:long trace(tree_ptr tp)    {        long ret = 0;        while(tp != NULL)        {           ret = tp->val;           tp = tp->left;        }        return ret;    } B:作用是从根一直遍历左子树,找到第一个没有左子树的节点的值. 3.70 A:long traverse(t

第三章 Linux操作系统的安装

第三章 Linux操作系统的安装 因为笔者一直都是使用CentOS,所以这次安装系统也是基于CentOS的安装.把光盘插入光驱,设置bios光驱启动.进入光盘的欢迎界面. 其中有两个选项,可以直接按回车,也可以在当前界面下输入 linux text 按回车.前者是图形下安装,可以动鼠标的,后者是纯文字形式的.建议初学者用前者安装.直接回车后,出现一下界面: 这一步是要提示你是否要校验光盘,目的是看看光盘中的安装包是否完整或者是否被人改动过,一般情况下,如果是正规的光盘不需要做这一步操作,因为太费