zoukankan      html  css  js  c++  java
  • C# 语法之泛型

    一.什么是泛型

      泛型其实就是一个不确定的类型,可以在类或方法上使用。泛型在声明期间没有明确定义类型,编译后生成一个占位符,只有在调用后传入类型,才会将该确切的类型将占位符替换掉。

    二.泛型的定义

    //用在类中
    public class ClassName<CName>
    {
        //用在方法中
        public void Mothed<MName>() {
            
        }
    
        //泛型类中具体使用CName
        //返回值为CName并且接受一个类型为CName类型的对象
        public CName GetC(CName c) {
    
        }
    }

      这里的CName和MName是可变的类型(名字也是可变),可以让调用者来决定要使用的类型。

    三.使用

      下面举个例子。

    public class Animal
    {
        //会跑的方法
        public virtual void CanRun()
        {
            Console.WriteLine("Animal Run Can");
        }
    }
    
    public class Dog : Animal
    {
        //重写父类方法
        public override void CanRun()
        {
            Console.WriteLine("Dog Can Run");
        }
    }
    
    public class Cat : Animal
    {
        //重写父类方法
        public override void CanRun()
        {
            Console.WriteLine("Cat Can Run");
        }
    }

      再定义一个animalHouse来存放所有的动物。

    public class AnimalHouse
    {
        private List<Animal> animals = new List<Animal>();
    
        //添加方法
        public void AddAnimal(Animal a)
        {
            animals.Add(a);
        }
    }

      AnimalHouse可以存放所有的动物,但如果取出来,使用就有些不方便。现在放进去Dog和Cat,你可以将所有动物都带出来跑步。假如Dog有个方法是Canswin()游泳的方法,那这里是调用不了,animal没有这个方法。

      如果使用泛型的话,就可以由调用者决定使用哪种类型。在AnimalHouse将所有animal改为泛型。

    public class AnimalHouse<T>
    {
        private List<T> animals = new List<T>();
    
        //添加方法
        public void AddAnimal(T a)
        {
            animals.Add(a);
        }
    }

      AnimalHouse想存放什么类型,由调用者决定。

    //声明存放所有Dog类型的集合
    AnimalHouse<Dog> dog = new AnimalHouse<Dog>();
    //声明存放所有Cat类型的集合
    AnimalHouse<Cat> cat = new AnimalHouse<Cat>();

      传入哪个类型,原本的T就会编译成具体的类型。animalHouse可以让我们来自己构造存放哪种动物的集合。该集合就可以具体使用集合中动物特有的方法。

      这里还有个问题,原本AnimalHouse只能存放animal,现在是泛型T,那就算是非animal的类也可以存进去,不符合最初的设计。所以为了类型安全,需要对传入的类型进行约束。

    四.泛型约束

      泛型约束就是对泛型(传入的类型)进行约束,约束就是指定该类型必须满足某些特定的特征,例如可以被实例化,实现Animal类等。举个例子。

    class Base { }
    class Test<T, U>
        where U : struct
        where T : Base, new()
    { }

      使用的话,只需要在泛型后面加上where来使用。

      where T : struct。类型必须为值类型。

      where T : class。类型必须为引用类型。

      where T : new()。类型参数必须具有公共无参数构造函数。 与其他约束一起使用时,new() 约束必须最后指定。

      where T : <基类名>。类型参数必须是指定的基类或派生自指定的基类。

      where T : <接口名称>。类型参数必须是指定的接口或实现指定的接口。 可指定多个接口约束。 约束接口也可以是泛型。

      然后,我们来为AnimalHouse添加泛型约束为:必须包含公共无参构造函数和基数必须为Animal。

    //Animal约束T必须是Animal的子类或者本身,new()约束放在最后
    public class AnimalHouse<T> where T : Animal, new()
    {
        private List<T> animals = new List<T>();
    
        //添加方法
        public void AddAnimal(T a)
        {
            //调用CanRun方法
            //如果不加Animal泛型约束是无法调用.CanRun方法的,因为类型是不确定的
            a.CanRun();
    
            animals.Add(a);
        }
    }

      现在AnimalHouse类限制要传入的参数是,必须继承Animal,且有公共无参构造函数的。

  • 相关阅读:
    Caused by: java.lang.IllegalStateException: Immutable bitmap passed to Canvas constructor
    Android 数据库 OrmLite Failed to open database
    【译】Android 数据库 ORMLite
    SIP
    Android LRUCache
    Enumeration与Iterator的对比
    URI, URL, and URN
    adb device offline 解决办法
    AudioFormat
    AudioTrack
  • 原文地址:https://www.cnblogs.com/shadoll/p/15308621.html
Copyright © 2011-2022 走看看