基类约束

基类约束有两个功能,首先,它允许泛型类使用基类约束所定义的的成员,第二个功能是确保泛型类使用指定基类的类型实参,这意味着,在使用泛型类时,类型实参必须是基类本身或者是派生自该基类的类。

class Program
    {
        static void Main(string[] args)
        {
            StudentList<Pupil> pupillist = new StudentList<Pupil>();
            StudentList<StudentBase> studentList = new StudentList<StudentBase>();
            pupillist.Add(new Pupil() { Name = "Bob", Age = 10, Chinese = 99, English = 99, Math = 99, Gender = Gender.Male });
            pupillist.Add(new Pupil() { Name = "Alice", Age = 10, Chinese = 100, English = 100, Math = 80, Gender = Gender.Female });
        }
    }
    enum Gender
    {
        Male,
        Female
    }
    //学生基类
    class StudentBase
    {
        public int Age { get; set; }
        public string Name { get; set; }
        public Gender Gender { get; set; }
    }
    //派生自学生基类的小学生类
    class Pupil:StudentBase
    {
        public int Chinese { get; set; }
        public int Math { get; set; }
        public int English { get; set; }
    }
    class StudentList<T> where T : StudentBase
    {
        List<T> Studentlist = new List<T>();
        public void Add(T t)
        {
            Studentlist.Add(t);
        }
        public void Delete(T t)
        {
            Studentlist.Remove(t);
        }
    }

上述代码定义了一个“学生基类”,其中包含三个属性:年龄,姓名,性别。毕竟只要你是学生, 你肯定有这三种最基本的属性。然后定义了一个小学生类,小学生肯定属于学生,所以继承了“学生基类”,除此之外,他们要学习语文数学英语三门科目,因此定义了这三项属性。
然后定义了一个学生列表泛型类,他有泛型基类约束where T : StudentBase,这个约束有两层含义,一层含义是说,在我定义的这个学生列表泛型类之中,我可以使用StudentBase这个“学生基类”所定义的成员,另一层含义是指,当我使用这个学生列表泛型类去创建对象的时候,<> 方括号里面必须是学生基类StudentBase本身或者是派生自学生基类StudentBase的其他类,前面所提到的类型实参 ,按个人理解,应该就是指方括号里面的东西。在这个例子里面,方括号可以填两种类型,一种是StudentBase,另一种是Pupil,填其他任何类型或者不填都会报错。

接口约束

接口约束是指定某个类型实参必须实现的接口。他的两个功能其实和基类约束一样,一个是允许在泛型类中使用接口的成员,另一个是要求类型实参必须是接口本身或者是实现接口的类,下面一个很简单的例子用来说明:

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Compare<int>.CompareTo(1, 2));//输出:2
            Console.WriteLine(Compare<string>.CompareTo("a", "b"));//输出:b
        }
    }
	//接口约束
    public class Compare<T> where T:IComparable
    {
        public static T CompareTo(T t1,T t2)
        {
            if (t1.CompareTo(t2) > 0)
            {
                return t1;
            }
            else
            {
                return t2;
            }
        }
    }

new()构造函数约束

new()构造函数约束允许开发人员实例化一个泛型类型的对象。new()约束要求类型实参必须提供一个无参数的公有构造函数。使用new()约束时,可以通过调用该无参数的构造函数来创建对象。new()构造函数约束的形式为:
where T:new ()
使用new()约束时应当注意3点:

  1. new()约束可以与其他约束一起使用,但必须位于约束列表的末端
  2. new()约束仅允许开发人员使用无参数的构造函数构造一个对象,即使同时存在其他的构造函数也是如此。即不允许给类型形参的构造函数传递实参。
  3. 不可以同时使用new()约束和值类型约束。因为值类型和new()都隐式的提供了一个无参公共构造函数。
class Pupil : StudentBase
    {
        public Pupil(int id)
        {

        }
        public Pupil()
        {

        }
        public int Chinese { get; set; }
        public int Math { get; set; }
        public int English { get; set; }
    }

给前述例子中的StudentList泛型类添加new()约束以后,在上述代码中,如果没有public Pupil() {}这个无参构造函数而仅仅有public Pupil(int id) { }这个含参构造函数的话,代码编译报错,提示:“Pupil”必须是具有公共的无参数构造函数的非抽象类型,才能用作泛型类型或方法“StudentList”中的参数“T” ,而且,如果要在泛型类实例化变量类型“T”,则同样需要new()约束,否则会编译报错。

引用/值类型约束

引用/值类型约束将一般类型参数约束为引用类型或值类型。
struct 约束将一般类型参数约束为值类型(例如,int、bool 和 enum);
class 约束将一般类型参数约束为引用类型(类)

组合约束

以上各种泛型约束可以进行组合,形成组合约束。组合约束要按一定顺序才能符合要求,它的第一项必须是引用/值类型约束或基类约束,接下来是接口约束,最后是new()约束。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐