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

   先说些题外话,只所以写这些东西。是看了CSDN上的曹版主的一篇:手把手教编程,不知道有没有人愿意参与。说实话,我工作四年,总感觉晕晕乎乎的,好多技术都

懂,但是没有一项是精通的。看了这篇帖子,说实在话我可想去,去聆听大神的教导。主要是想提高自己,由于没有时间,又因为身在北京。所以就没有报名(呵呵,报名也

可能没有机会去)。所以自己就去图书馆去搞他提出的这些概念。其实我更希望在北京的大神们也能组织类似的活动。我想响应一定也很多,其实我想如果能组织一次这样的

活动,大神们也会得到提高的。这些都是我在图书馆看书的所得,分享给大家,同时也请管理员同志手下留情,不要每一篇都给打入冷宫,我已经很用心去做了。另外对这

感兴趣的童鞋们可以加我的QQ348537081,我们可以讨论一下心得。最后喜欢看书的童鞋也可以联系我,每周六首都图书馆,风雨无阻。

  说的有些多,下面转入正题。其实这篇文章是泛型介绍(接上一篇,具体的事例随后呈上)的扩展与修改。

因为家中无法联网,我都是提前用wps提前写好的,所有格式上可能会有一些问题,所以请大家多担待。

2.2接口约束(where T:interface-name)

  为了规定某个数据类型必须实现某个接口,需要声明一个接口约束(interface constraint).有了这种约束之后,甚至不需要执行类型转换,就可以调用一个显示的接口成员实现.接

口约束的主要功能与基类约束完全一样。首先,它允许开发人员在泛型类中使用接口的成员。其次,它确保只能使用实现了特定接口的类型实参。这意味着对于任何给定的接

口约束,类型实参要么是接口本身,要么实现了接口的类。

注:可以通过使用逗号分隔的列表来同时指定多个接口。如果某个约束同时包含基类和接口,则先指定基类再指定接口列表。

如:为了确保T类型参数都是先了IComparable接口,

public class Binary<T> where T:System.IComparable{...}

编译器会确保每次使用Binary类的时候,都必须指定一个实现了IComparable接口的类型参数.

  下面的程序通过改写前一个程序中的电话列表程序来说明接口约束的用途。在此程序中,PhoneNumber类被转换为一个名为IPhoneNumber的接口。然后,Friend和Supplier实现了该接口。

class NotFoundException1 : Exception
    {
        public NotFoundException1() : base() { }

        public NotFoundException1(string str) : base(str) { }

        public NotFoundException1(string str, Exception inner) : base(str, inner) { }

        protected NotFoundException1(System.Runtime.Serialization.SerializationInfo si,
            System.Runtime.Serialization.StreamingContext sc)
            : base(si, sc) { }
    }

    public interface IPhoneNumber
    {
        public string Number { get; set; }

        public string Name { get; set; }
    }

    public class Friend1 : IPhoneNumber
    {
        public string Number { get; set; }

        public string Name { get; set; }

        public bool IsWorkNumber { get; set; }

        public Friend1(string name, string num, bool wk)
        {
            Name = name;
            Number = num;
            IsWorkNumber = wk;
        }
    }

    public class Supplier1 : IPhoneNumber
    {
        public string Name { get; set; }

        public string Number { get; set; }

        public Supplier1(string name, string num)
        {
            this.Name = name;
            this.Number = num;
        }
    }

    class FriendEmail1 { }

    class PhoneList1<T> where T : IPhoneNumber
    {
        T[] phList;
        int end;

        public PhoneList1()
        {
            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)
        {
            foreach (T item in phList)
            {
                if (item.Name == name)
                    return item;
            }

            throw new NotFoundException1();
        }

        public T FindByNum(string num)
        {
            foreach (T item in phList)
            {
                if (item.Number == num)
                    return item;
            }

            throw new NotFoundException1();
        }

2.3 struct/class 约束(where T:class/struct)

    另一个重要的泛型约束是将类型参数限制为一个值类型或者一个引用类型.编译器不允许在一个约束中将System.ValueType指定成基类.相反,C#提供了特殊的语法,这种语法同时适用于引用类型.在这种语法中,不是为T指定一个基类.相反,只需要指定关键字struct或者class.在同时存在其他约束时,class或者struct必须位于约束列表的开头

例:

Public struct Nullable<T>:IFormattable,IComparable,IComparable<Nullable<T>>,INullable where T:struct

{//.......}

2.4 new()构造函数约束

  New()构造函数约束允许开发人员实例化一个泛型类型的对象。一般情况下,无法创建一个泛型类型参数的实例。然而,new()约束改变了这种情况,它要求类型实参必须

提供一个无参数的构造函数。在使用new()约束的时候,可以通过调用该无参构造函数来创建对象。

class myclass

        {

            public myclass() { }

        }

        class Test<T> where T : new() 

        {

            T obj;

            public Test() 

            {

                obj = new T();

            }

        }

调用:

 Test<myclass> x = new Test<myclass>();

注意:myclass 不必显示地声明一个无参数构造函数,默认的构造函数也可以满足这种约束。然而,如果某个类除了无参的构造函数外还需要定义其他的构造函数,那么必须

为该类显式地声明不含参数的构造函数。

使用new()时,应注意三点:

一、它可以和其他约束一起使用,但必须位于约束列表的末端。

二、New()不允许给类型参数的构造函数传递实参

三、不可以同时使用new()约束和值类型约束

2.5多重约束

  同一个参数可以使用多个约束。这种情况下,需要使用一个逗号分隔的约束列表.在该列表中,第一个约束必须是class或者struct(如果存在的话),或者基类(如果被指

定)。指定class或者struct的同时也指定基类约束是非法的。接下来是接口约束。最后是new ()约束。如:

Class Gen<T> where T:myClass,IMyInterface,new(){}

如果有多个类型参数,那么每个类型名称的前面都要使用一个where关键字.如:

Class Gen<T,V> where T:class
Where T:struct
{//.....}

2.6.泛型方法

为了定义泛型方法,需要紧接在方法名之后添加类型参数语法,如

public T method<T>(T params)
{
return params;
}

泛型方法也允许指定约束:

public T method<T>(T params)
where T:IComparable
{
return params;
}

2.7.Default关键字:

  要确定用于创建泛型类实例的类型,需要了解一个最基本的情况:他们是引用类型还是值类型.若不知道这个情况,就不能用下面的代码赋予null值:

public class myGenericClass<T1,T2,T3>
{
    T1 t1;
    public myGenericClass()
{
    t1=null;
}
}

如果T1是值类型,则t1不能是null,所以这段代码将不会编译.幸好,我们可以用default关键字的新用法解决了它.

public myGenericClass()
{
  t1=default(T1);
}

其结果是:如果t1是引用类型,就给它赋予null,如果它是值类型,就赋予默认值.如数字类型,这个默认值就是0.

几个泛型类型的示例:

2.8定义泛型结构

public struct myStruct<T1,T2>
{
  public T1 item1;
  public T2 item2;
}

2.9定义泛型接口   interface myInterfacee<T>{}

2.10 .定义泛型方法

 public T GetDefault<T>()
{
  return default(T);
}

2.11定义泛型委托

  public delegate T1 myDelegate<T1,T2>(T2 op1,T2 op2) where T1:T2

  结束语:泛型到这了,下一次介绍下反射,关于前几篇C#我会抽时间重新写的,能让他更详细点,其实这次C#基础知识的复习让我学到很多东西,以前模糊的概念,

现在变得非常清晰了。我曾经面试过好多人,有工作三年,有两年,甚至工作经验比我还长的。对这些基础性的知识都知之甚少,当然也包括我自己。因为如果没

有这些概念,工作中也不会可虑到这些东西,当然也就谈不上引用。所以我们都只能做底层程序。程序猿想提高,重新学这些基础知识吧,真的……

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏MyBlog

Effective.Java 读书笔记(8)关于equals方法

重写equals看上去十分简单对吧,但是我觉得很多时候重写equals可能会招致一些问题,这些问题有时可能会特别严重,当然了不重写不就完事了吗?但是这只适用于那...

914
来自专栏blackheart的专栏

[程序设计语言]-[核心概念]-03:控制流

0.概述 前面介绍了语言的演进以及一些基础概念后,从本篇开始进入了语言的核心问题中。这一篇讨论的是语言计算模型(大致可以用控制流来表述),大致如下7种: 顺序执...

21310
来自专栏北京马哥教育

Python 算法实战系列:栈

学Python最简单的方法是什么?推荐阅读:Python开发工程师成长魔法 栈(stack)又称之为堆栈是一个特殊的有序表,其插入和删除操作都在栈顶进行操作,并...

3618
来自专栏ACM算法日常

简单计算器(栈的变种)- HDU 1237

测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输...

1271
来自专栏HTML5学堂

原生JS | 数据类型检测,并没你想象的那么简单

HTML5学堂-码匠:看上去,JavaScript中的数据类型检测,并没有什么难度,但是……它包含了不少的知识,如果你只知道一个typeof的话,那很建议你读读...

3405
来自专栏编程

浅谈如何定义和调用Python的函数

函数是python编程核心内容之一,笔者在本文中主要介绍下函数的概念和基础函数相关知识点。函数是什么?有什么作用、定义函数的方法及如何调用函数。 函数是可以实现...

1835
来自专栏深度学习自然语言处理

介绍4个大神常用而你不常用的python函数

1101
来自专栏大数据钻研

如何正确实现Java中的hashCode方法

你知道一个对象的唯一标志不能仅仅通过写一个漂亮的equals来实现 太棒了,不过现在你也必须实现hashCode方法。 让我们看看为什么和怎么做才是正确的。 相...

2859
来自专栏码农阿宇

C# 扩展方法 白话总结

我们在变成的时候时常遇到这样的问题,new了一个系统内的对象之后,我们想要对该对象有一个方法可是却点不出来,说明该对象本身没有声明该方法,可是微软又不允许我们去...

2859
来自专栏zhisheng

运算优先级、结合性、求值顺序、副作用和顺序点

标题中这几个概念,是很多C/C++程序员在表达式上容易出问题或不清楚的地方,虽然这些概念在很多语言都有体现,但C里面特别明显,所以就以C语言为例子总结下 运算...

4837

扫码关注云+社区

领取腾讯云代金券