当前位置: 移动技术网 > IT编程>开发语言>.net > .NET基础之自定义泛型

.NET基础之自定义泛型

2019年05月10日  | 移动技术网IT编程  | 我要评论

独爱冷夫君,吉田亚纪子白雪,网站搜索排名

在.net中泛型使用非常频繁,在控制台应用程序中,默认的引入了system.collection.generics名称空间,其中就提供了我们经常使用的泛型:list<t>和dictionary<t>,相信用过它们的都知道它们的强大。还有一种我们经常使用的简单的泛型:system.nullable<t>,即可空类型。我们可以:

 

system.nullable<int> nullableint;

声明一个可空的int类型,由于c#语法对这个做了简化通常我们都不这样写,而是这样写:

 

int? nullableint

下面重点介绍一下如何自定义泛型。

 

 

 

定义泛型类

 

创建泛型类是需要在类定义中用尖括号语法:

 

class mygenericclass<t>

{

    ...

}

t可以是任意的标示符,只要遵守命名规则即可。

 

 

 

可以把类型用在类成员的返回类型,方法参数类型等,例如:

 

复制代码

class mygenericclass<t1, t2, t3>

{

    private t1 t1object;

 

    public mygenericclass(t1 item)

    {

        t1object = item;

    }

 

    public t1 t1object

    {

        get

        {

            return t1object;

        }

    }

}

复制代码

注意如果不能假定提供了什么类型。下面的代码不能执行:

 

复制代码

class mygenericclass<t1, t2, t3>

{

    private t1 t1object;

 

    public mygenericclass()

    {

        t1object = new t1();

    }

}

复制代码

因为我们不知道t1是否有公有的默认构造函数。

 

 

 

default关键字

 

如果我们定义了一个泛型的字段,我们想在构造函数中初始化它,但是我们不知道它的引用类型还是值类型,那么default就派上用处了:

 

public mygenericclass()

{

    t1object = default(t1);

}

如果是值类型就赋值0,引用类型就赋值null。

 

 

 

约束类型

 

在定义泛型的时候我们可以对类型进行约束,通过where关键字实现:

 

class mygenericclass<t1> where t : constraint1,constraint

{

    ...

}

constraint定义了约束,多个约束用逗号隔开,如果有多个类型:

 

class mygenericclass<t1, t2> where t1 : constraint1 where t2 : constraint

{

    ...

}

下面给出一些可用的约束

 

                                        约束                                                                  说明

 

                                where t:struct                                     使用结构约束,类型t必须是值类型

 

                                where t:calss                                       类约束指定,类型t必须是引用类型

 

                                where t:interface                                  指定类型t必须实现是接口或者实现了接口

 

                                where t:base-class                               指定类型t必须是基类或者派生于基类

 

                               where t:new()                                       指定类型t必须有一个默认构造函数

 

 

 

下面结合以上知识给个实例:(ps不要看到代码多 其实很简单的 耐心看下去)

 

先定义四个类animal、cow 、chicken和supercow

 

复制代码

#region animal 虚基类 有一个name属性 feed方法和一个虚方法makeanoise

    //虚基类 有一个name属性 feed方法和一个虚方法makeanoise

    public abstract class animal

    {

        protected string name;

 

        public string name

        {

            get

            {

                return name;

            }

            set

            {

                name = value;

            }

        }

 

        public animal()

        {

            name = "the animal with no name";

        }

 

        public animal(string newname)

        {

            name = newname;

        }

 

        public void feed()

        {

            console.writeline("{0} has been fed.", name);

        }

 

        public abstract void makeanoise();

    }

    #endregion

复制代码

复制代码

//cow animal的子类,实现虚方法

    public class cow:animal

    {

        public cow(string name) :

            base(name)

        {

        }

        public override void makeanoise()

        {

            console.writeline("{0} says 'moo!'", name);

        }

    }

复制代码

复制代码

//chicken类,animal子类

    public class chicken:animal

    {

        public chicken(string name)

            : base(name)

        { }

        public override void makeanoise()

        {

            console.writeline("{0} says 'cluck'", name);

        }

    }

复制代码

复制代码

//cow的子类,有一个自己的方法fly

    class supercow : cow

    {

        public supercow(string name) : base(name) 

        {

        }

 

        public void fly()

        {

            console.writeline("{0} is flying!", name);

        }

 

        public override void makeanoise()

        {

            console.writeline("{0} says 'i am supercow!'", name);

        }

 

    }

复制代码

类准备好了之后,我们可以开始定义我们的泛型了:

 

复制代码

//继承了迭代器接口,这样方便使用foreach 约束它的类型为animal及其子类

    public class farm<t>:ienumerable<t> where t : animal

    {

        private list<t> animals = new list<t>();

 

        public list<t> animals

        {

            get 

            {

                return animals;    

            }

        }

        //迭代器

        public ienumerator<t> getenumerator()

        {

            return animals.getenumerator();

        }

 

        ienumerator ienumerable.getenumerator()

        {

            return animals.getenumerator();

        }

 

        //执行所有animal的makeanoise()

        public void makenoises()

        {

            foreach (t animal in animals)

            {

                animal.makeanoise();

            }

        }

        //执行所有animal的feed()

        public void feedtheanimals()

        {

            foreach (t animal in animals)

            {

                animal.feed();

            }

        }

        //获得animals中的cow

        public farm<cow> getcows()

        {

            farm<cow> cowfarm = new farm<cow>();

            foreach (t animal in animals)

            {

                if (animal is cow)

                {

                    cowfarm.animals.add(animal as cow);

                }

            }

            return cowfarm;

        }

    }

复制代码

泛型定义好了,我们用写代码来调用它:

 

复制代码

class program

    {

        static void main(string[] args)

        {

            farm<animal> farm = new farm<animal>();

            farm.animals.add(new cow("jack"));

            farm.animals.add(new chicken("vera"));

            farm.animals.add(new chicken("sally"));

            farm.animals.add(new supercow("kevin"));

            farm.makenoises();

 

            farm<cow> dairyfarm = farm.getcows();

            dairyfarm.feedtheanimals();

 

            foreach (cow cow in dairyfarm)

            {

                if (cow is supercow)

                {

                    (cow as supercow).fly();

                }

            }

            console.readkey();

        }

    }

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网