看到他我一下子就悟了-- 泛型(1)

1.泛型概念:

      本质上,术语”泛型”指的是”参数化类型(parameterized types)”.参数化类型非常重要,因为它们可以在创建类.结构.方法和委托的时候将要操作的数据类型作为参

数进行指定.使用参数化类型的类.结构.方法和委托都可以称为泛型,如”泛型类”或者”泛型方法”.

       在具体声明一个变量或者实例化之前,类型参数T只是一个占位符。等到具体声明和实例化的时候,编译器要求代码指定类型参数。泛型类型声明了泛型参数占位符类型,由泛型类型的用户填写这些占位符,并作为泛型的参数提供给泛型类型.

 

2.泛型约束:约束声明了泛型要求的类型参数的特征。

    为了声明一个约束,需要使用where关键字,后跟一对”参数:要求”.其中,”参数”必须是泛型类型中定义的一个参数,而”要求”用于限制类型从

中”派生”的类或接口,或者限制必须存在一个默认构造器,或者限制使用一个引用/值类型约束.

2.1基类约束(where T:base-class-name)

       有的时候,你可能需要限制类型从一个特定的类派生.这是用基类约束(base class constraint)做到的.使用基类约束,可以指定某个类型实参

必须继承的基类.基类约束有两个重要功能.

  首先,他允许在泛型类中使用由约束指定的基类所定义的成员.例如,可以调用基类的方法或者使用基类的属性.如果没有基类约束,编译器就无法知道某

个类型实参拥有哪些成员.通过提供基类约束,编译器将知道所有的类型实参都拥有由指定的基类所定义的成员.

  基类约束的第二个功能是,确保只适用支持指定基类的类型实参.这意味着对于任意给定的基类约束,类型实参要么是基类本身,要么是派生于该基

类.如果试图使用没有匹配或者继承指定的类型实参,就会导致编译错误 例:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//泛型:基类约束
//基类约束两个作用:1.基类约束允许泛型类访问基类的成员
// 2.确保只能使用满足该约束的类型参数,从而实现类型安全
namespace generic
{
/*案例描述:假设要创建一个管理电话号码列表的工具.另外,假定不同组的用户
使用的是不同的列表.例如,一个列表用于朋友,令外一个列表用于供应商等.
*/

/// <summary>
/// PhoneNumber基类,它用于存储姓名和姓名相对应的电话号码
/// </summary>
class PhoneNumber
{
public string Number { get; set; }
public string Name { get; set; }

public PhoneNumber(string n, string num)
{
this.Name = n;
this.Number = num;
}
}

/// <summary>
/// 朋友电话
/// </summary>
class Friend : PhoneNumber
{
/// <summary>
/// 电话号码是否为工作号码
/// </summary>
public bool IsWorkNumber { get; private set; }

public Friend(string n, string num, bool wk)
: base(n, num)
{
this.IsWorkNumber = wk;
}
}

/// <summary>
/// 供应商电话
/// </summary>
class Supplier : PhoneNumber
{
public Supplier(string n, string num)
: base(n, num)
{
}
}
/*为了管理电话列表,下面创建一个名为PhoneList的类.由于希望该类能够
* 管理任意类型的电话列表,因此将其实现为泛型.另外,由于列表管理的一部分内容是
* 根据姓名查询号码,或者根据号码查询姓名,因此要给它添加约束,从而
* 确保存储在列表中的对象的类型必须是PhoneNumber派生类的实例
*/

/// <summary>
/// 管理任意类型的电话列表
/// </summary>
/// <typeparam name="T"></typeparam>
class PhoneList<T> where T:PhoneNumber
{
T[] phList;

int end;

public PhoneList()
{
phList = new T[10];
end = 0;
}

public bool Add(T newEntry)
{
if (end == 10) return false;

phList[end] = newEntry;
end++;

return true;
}

public T FindByName(string name)
{
for (int i = 0; i < end; i++)
{
if (phList[i].Name == name)
return phList[i];
}

throw new NotFoundException();
}

public T FindByNumber(string number)
{
for (int i = 0; i < end; i++)
{
if (phList[i].Number == number)
return phList[i];
}

throw new NotFoundException();
}
}

/// <summary>
/// 此类没有继承PhoneNumber,因此不能用于创建PhoneList
/// </summary>
class EmailFriend
{
//.....
}
/*
* 这是一个定制异常,虽然该示例只使用默认构造函数,但是出于说明的
* 目的,NotFoundException实现了Exception定义的所有构造函数
* 注意:这些构造函数只调用了Exception定义的相等基类构造函数.
* NotFoundException没有向Exception添加任何内容,因此不需要
* 执行任何进一步的操作
*/
class NotFoundException : Exception
{
public NotFoundException():base(){}
public NotFoundException(string str):base( str){}
public NotFoundException(string str, Exception inner) :
base(str, inner) { }
protected NotFoundException(
System.Runtime.Serialization.SerializationInfo si,
System.Runtime.Serialization.StreamingContext se) :
base(si, se) { }
}
}

 

怎样调用:

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

namespace generic
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseClassConstraint();
            Console.Read();
        }

        //基类约束
        public static void BaseClassConstraint()
        {
           //可以通过编译
            PhoneList<Friend> plist = new PhoneList<Friend>();
            //错误添加
            //plist.Add(new Friend() {Name="Tom",Number="555-1234",IsWorkNumber=true });
        //正确添加
            plist.Add(new Friend("Tom", "5555-333", true));
            plist.Add(new Friend("Gary", "5555-332", true));
            plist.Add(new Friend("WangC", "5555-331", false));

            try
            {
                Friend frnd = plist.FindByName("Gary");
                Console.WriteLine(frnd.Name+":"+frnd.Number);

                if(frnd.IsWorkNumber)
                    Console.WriteLine("(work)");
                else
                    Console.WriteLine();
            }
            catch (NotFoundException)
            {
                Console.WriteLine("Not Found");
            }

            //供应商
            PhoneList<Supplier> plist2 = new PhoneList<Supplier>();
            plist2.Add(new Supplier("Global Hardware", "400-123"));
            plist2.Add(new Supplier("Computer", "400-124"));
            plist2.Add(new Supplier("NetWorkCity", "400-125"));

            try
            {
                Supplier sp = plist2.FindByNumber("400-124");
                Console.WriteLine(sp.Name+":"+sp.Number);
            }
            catch (NotFoundException)
            {
                Console.WriteLine("Not Found");
            }

            //没有继承的
           // PhoneList<EmailFriend> plist3 = new PhoneList<EmailFriend>();
        }
    }

}

 未完待续……

时间: 2024-09-26 05:32:18

看到他我一下子就悟了-- 泛型(1)的相关文章

看到他我一下子就悟了-- 泛型(2)

   先说些题外话,只所以写这些东西.是看了CSDN上的曹版主的一篇:手把手教编程,不知道有没有人愿意参与.说实话,我工作四年,总感觉晕晕乎乎的,好多技术都 懂,但是没有一项是精通的.看了这篇帖子,说实在话我可想去,去聆听大神的教导.主要是想提高自己,由于没有时间,又因为身在北京.所以就没有报名(呵呵,报名也 可能没有机会去).所以自己就去图书馆去搞他提出的这些概念.其实我更希望在北京的大神们也能组织类似的活动.我想响应一定也很多,其实我想如果能组织一次这样的 活动,大神们也会得到提高的.这些都

看到他我一下子就悟了---委托

看到大家的留言,我想说下我对委托的了解,首先看它的定义: 委托 就是将方法作为方法的参数 不用先看例子什么的,你就多品味品味这句话,然后你看下使用委托的步骤, 1.定义一个委托 2.注册该委托 3.使用委托 Ok就这么简单,其实委托就像大家常说的那样: 它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里憋得慌,浑身不自在 其实不用怕,你就按着这三步来标准没错,下面来个小例子: 第一步:定义委托 public delegate void Greetin

C#基础知识回顾--委托事件

在上一篇看到他我一下子就悟了(续)---委托,被人狂喷.说写的太空,没有什么内容之类的.所以准备在这里重写下,不过还是按着以前的方式尽量简单的写.这里我们以打篮球为例. 第一步:首先,其他对象订购事件        当发球的球员产生它的发球事件之前,其他球员需要订购这个事件,采用这种方式,只要出现一个发球事件,其他球 员就能够知道.   第二步:触发事件        当球被发出时,此时发球员对象产生一个新事件.   第三步:球产生一个事件          创建一个新事件,这个事件还有一些参数

参悟JavaScript

引子     编程世界里只存在两种基本元素,一个是数据,一个是代码.编程世界就是在数据和代码千丝万缕的纠缠中呈现出无限的生机和活力.     数据天生就是文静的,总想保持自己固有的本色:而代码却天生活泼,总想改变这个世界.    你看,数据代码间的关系与物质能量间的关系有着惊人的相似.数据也是有惯性的,如果没有代码来施加外力,她总保持自己原来的状态.而代码就象能量,他存在的唯一目的,就是要努力改变数据原来的状态.在代码改变数据的同时,也会因为数据的抗拒而反过来影响或改变代码原有的趋势.甚至在某些

李战:悟透JavaScript

多年前,曾经看过李战大师的"悟透delphi-delphi的原子世界",一直对大师特有的文笔风格记忆犹新,今天无意又看到了大师的"李战:悟透JavaScript",转贴于此,与众分享!   引子    编程世界里只存在两种基本元素,一个是数据,一个是代码.编程世界就是在数据和代码千丝万缕的纠缠中呈现出无限的生机和活力.     数据天生就是文静的,总想保持自己固有的本色:而代码却天生活泼,总想改变这个世界.    你看,数据代码间的关系与物质能量间的关系有着惊人的相

悟透JavaScript整理版第1/2页_javascript技巧

数据天生就是文静的,总想保持自己固有的本色:而代码却天生活泼,总想改变这个世界.    你看,数据代码间的关系与物质能量间的关系有着惊人的相似.数据也是有惯性的,如果没有代码来施加外力,她总保持自己原来的状态.而代码就象能量,他存在的唯一目的,就是要努力改变数据原来的状态.在代码改变数据的同时,也会因为数据的抗拒而反过来影响或改变代码原有的趋势.甚至在某些情况下,数据可以转变为代码,而代码却又有可能被转变为数据,或许还存在一个类似E=MC2形式的数码转换方程呢.然而,就是在数据和代码间这种即矛盾

悟透JavaScript出版啦

前天李战老师发消息来说我们合作的<悟透JavaScript>终于出版了 下午兴冲冲拿到样书,第一次看着自己的涂鸦变成印刷品,自然是十分激动 没错,就是涂鸦! 当然,这其实是一本讲JavaScript的好书 至于为什么会有这么神奇的一本程序书籍,却有一段小故事 当时出版社决定打破技术书籍沉闷的惯例 让这本书读起来更加有趣一点 可惜找了好几个插画er都不尽如人意 程序员和艺术家也许很难沟通 结果刚好碰上我这个懂一点编程又懂一点漫画的打杂小妹 于是李老师决定慷慨的给我这个机会为本书配置插图 从此后的

从《甄嬛传》中悟出的SEO心得体会

最近时间,<甄嬛传>很火,有网友甚至感叹迷倒主妇级观众,求放过我妈.今天不是说<甄嬛传>剧情,而是通过这部电视剧中能够悟出一些SEO道理.有的人就说,你又开始胡扯了,一部电视剧怎么还和我们优化这个行业有联系呢.其实我们做SEO的人不就是要一个发散思维么,哪里有热点,哪里就有我们的存在.世间万物都有有关联,只是要看我们从哪个角度出发,当我们发现了,就会给人眼前一亮之惊喜. 先来说说<甄嬛传>看完后的一点感悟,之后这个SEO心得体会.后宫佳丽三千,要想永远得到皇上的宠爱,就

刘金鸽:做菜过程中悟出的SEO学问

在我们生活中,只要你留心都会有学问.要不然古人怎么会总结出一句话"处处留心皆学问".其实,我在做菜的过程中就误出了一个道理,做SEO就像做菜一样,虽说材料不同,但是他们的原理都是相同的.而对优化这个词我有一个新的解释,优化就是用质优的网站来化解人们心中的疑问.接下来我就给大家具体讲一下我悟出来看学问. 在大家做SEO的过程中,都会有这样的感觉:就是SEO说来说去就是那些东西,没有什么新意.而创新这个东西是靠我们大家来想出来的,我们可以旧瓶装新酒,这样就会有别样的感觉,当大家看我的到标题