【C#补全计划】泛型约束
一、泛型约束的概念
1. 作用:让泛型的类型有一定的限制
2. 关键字:where
3. 种类:6种
(1)值类型: struct
(2)引用类型:class
(3)无参的公共构造函数:new()
(4)某个类本身或其派生类:类名
(5)某个接口的派生类:接口名
(6)另一个泛型类本身或其派生类型:其他泛型
4. 语法:where 泛型 : 种类
二、泛型约束的使用
1. 值类型
using System;namespace GenericConstraints
{class Program{static void Main(string[] args){// Test<object> t1 = new Test<object>(); 编译报错:因为Test1是值类型约束,而object是引用类型Test1<int> t1 = new Test1<int>();t1.fun(123);}}// 值类型class Test1<T> where T : struct{public T value;public void fun<K>(K k) where K : struct{Console.WriteLine(k + "是值类型");}}
}
2. 引用类型
using System;namespace GenericConstraints
{class Program{static void Main(string[] args){// Test<object> t1 = new Test<object>(); 编译报错:因为Test1是值类型约束,而object是引用类型Test1<int> t1 = new Test1<int>();t1.fun(123);// Test2<int> t2 = new Test2<int>(); 编译报错:因为Test2是引用类型约束,而int是值类型Test2<object> t2 = new Test2<object>();t2.fun(new Random());}}// 值类型class Test1<T> where T : struct{public T value;public void fun<K>(K k) where K : struct{Console.WriteLine(k + "是值类型");}}// 引用类型class Test2<T> where T : class{public T value;public void fun<K>(K k) where K : class{Console.WriteLine(k + "是引用类型");}}
}
3. 存在公共的无参构造函数
using System;namespace GenericConstraints
{class Program{static void Main(string[] args){// Test<object> t1 = new Test<object>(); 编译报错:因为Test1是值类型约束,而object是引用类型Test1<int> t1 = new Test1<int>();t1.fun(123);// Test2<int> t2 = new Test2<int>(); 编译报错:因为Test2是引用类型约束,而int是值类型Test2<object> t2 = new Test2<object>();t2.fun(new Random());// Test3<A> t3 = new Test3<A>(); 编译报错:因为Test3是无参公共构造函数约束,而A没有公共无参构造函数Test3<B> t3 = new Test3<B>();t3.fun(new B());}}// 值类型class Test1<T> where T : struct{public T value;public void fun<K>(K k) where K : struct{Console.WriteLine(k + "是值类型");}}// 引用类型class Test2<T> where T : class{public T value;public void fun<K>(K k) where K : class{Console.WriteLine(k + "是引用类型");}}// 存在公共无参构造函数class Test3<T> where T : new(){public T value;public void fun<K>(K k) where K : new(){Console.WriteLine(k + "有公共无参构造方法");}}class A{private int value;public A(int value){this.value = value;}}class B{public B() {}}
}
4. 是某个类本身或其派生类
using System;namespace GenericConstraints
{class Program{static void Main(string[] args){// Test<object> t1 = new Test<object>(); 编译报错:因为Test1是值类型约束,而object是引用类型Test1<int> t1 = new Test1<int>();t1.fun(123);// Test2<int> t2 = new Test2<int>(); 编译报错:因为Test2是引用类型约束,而int是值类型Test2<object> t2 = new Test2<object>();t2.fun(new Random());// Test3<A> t3 = new Test3<A>(); 编译报错:因为Test3是无参公共构造函数约束,而A没有公共无参构造函数Test3<B> t3 = new Test3<B>();t3.fun(new B());// Test4<Test1<int>> t4 = new Test4<Test1<int>>(); 编译报错:因为Test4是Test2或其子类约束,而Test1不是Test2或其子类Test4<Test2<object>> t4 = new Test4<Test2<object>>();t4.fun(new Test2<object>());}}// 值类型class Test1<T> where T : struct{public T value;public void fun<K>(K k) where K : struct{Console.WriteLine(k + "是值类型");}}// 引用类型class Test2<T> where T : class{public T value;public void fun<K>(K k) where K : class{Console.WriteLine(k + "是引用类型");}}// 存在公共无参构造函数class Test3<T> where T : new(){public T value;public void fun<K>(K k) where K : new(){Console.WriteLine(k + "有公共无参构造方法");}}class A{private int value;public A(int value){this.value = value;}}class B{public B() {}}class Test4<T> where T : Test2<object>{public T value;public void fun<K>(K k) where K : Test2<object>{Console.WriteLine(k + "是Test2类或其派生类");}}
}
5. 是某个接口的派生类型
using System;namespace GenericConstraints
{class Program{static void Main(string[] args){// Test<object> t1 = new Test<object>(); 编译报错:因为Test1是值类型约束,而object是引用类型Test1<int> t1 = new Test1<int>();t1.fun(123);// Test2<int> t2 = new Test2<int>(); 编译报错:因为Test2是引用类型约束,而int是值类型Test2<object> t2 = new Test2<object>();t2.fun(new Random());// Test3<A> t3 = new Test3<A>(); 编译报错:因为Test3是无参公共构造函数约束,而A没有公共无参构造函数Test3<B> t3 = new Test3<B>();t3.fun(new B());// Test4<Test1<int>> t4 = new Test4<Test1<int>>(); 编译报错:因为Test4是Test2或其子类约束,而Test1不是Test2或其子类Test4<Test2<object>> t4 = new Test4<Test2<object>>();t4.fun(new Test2<object>());// Test5<A> t5 = new Test5<A>(); 编译报错:因为Test5是ITest接口实现类约束,而A没有实现ITest接口Test5<C> t5 = new Test5<C>();t5.fun(new C());}}// 值类型class Test1<T> where T : struct{public T value;public void fun<K>(K k) where K : struct{Console.WriteLine(k + "是值类型");}}// 引用类型class Test2<T> where T : class{public T value;public void fun<K>(K k) where K : class{Console.WriteLine(k + "是引用类型");}}// 存在公共无参构造函数class Test3<T> where T : new(){public T value;public void fun<K>(K k) where K : new(){Console.WriteLine(k + "有公共无参构造方法");}}class A{private int value;public A(int value){this.value = value;}}class B{public B() {}}class Test4<T> where T : Test2<object>{public T value;public void fun<K>(K k) where K : Test2<object>{Console.WriteLine(k + "是Test2类或其派生类");}}// 接口约束class Test5<T> where T : ITest{public T value;public void fun<K>(K k) where K : ITest{Console.WriteLine(k + "是ITest接口的派生类");}}interface ITest { }class C : ITest { }
}
6. 是另一个泛型类本身或其派生类型
using System;namespace GenericConstraints
{class Program{static void Main(string[] args){// Test<object> t1 = new Test<object>(); 编译报错:因为Test1是值类型约束,而object是引用类型Test1<int> t1 = new Test1<int>();t1.fun(123);// Test2<int> t2 = new Test2<int>(); 编译报错:因为Test2是引用类型约束,而int是值类型Test2<object> t2 = new Test2<object>();t2.fun(new Random());// Test3<A> t3 = new Test3<A>(); 编译报错:因为Test3是无参公共构造函数约束,而A没有公共无参构造函数Test3<B> t3 = new Test3<B>();t3.fun(new B());// Test4<Test1<int>> t4 = new Test4<Test1<int>>(); 编译报错:因为Test4是Test2或其子类约束,而Test1不是Test2或其子类Test4<Test2<object>> t4 = new Test4<Test2<object>>();t4.fun(new Test2<object>());// Test5<A> t5 = new Test5<A>(); 编译报错:因为Test5是ITest接口实现类约束,而A没有实现ITest接口Test5<C> t5 = new Test5<C>();t5.fun(new C());// Test6<C, E> t6 = new Test6<C, E>(); 编译报错:因为Test6是另一个泛型类或及其派生类约束,而C不是E或其派生类Test6<D, E> t6 = new Test6<D, E>();t6.fun<D, E>(new D());}}// 值类型class Test1<T> where T : struct{public T value;public void fun<K>(K k) where K : struct{Console.WriteLine(k + "是值类型");}}// 引用类型class Test2<T> where T : class{public T value;public void fun<K>(K k) where K : class{Console.WriteLine(k + "是引用类型");}}// 存在公共无参构造函数class Test3<T> where T : new(){public T value;public void fun<K>(K k) where K : new(){Console.WriteLine(k + "有公共无参构造方法");}}class A{private int value;public A(int value){this.value = value;}}class B{public B() {}}class Test4<T> where T : Test2<object>{public T value;public void fun<K>(K k) where K : Test2<object>{Console.WriteLine(k + "是Test2类或其派生类");}}// 接口约束class Test5<T> where T : ITest{public T value;public void fun<K>(K k) where K : ITest{Console.WriteLine(k + "是ITest接口的派生类");}}interface ITest { }class C : ITest { }// 泛型类及其派生类约束class Test6<T, M> where T : M{public T value;public void fun<K, V>(K k) where K : V{Console.WriteLine(k + "是" + typeof(V) + "或其派生类");}}class E { }class D : E { }
}
运行结果如下:
三、泛型有多个约束
using System;namespace GenericConstraints
{class Program{static void Main(string[] args){// Test<object> t1 = new Test<object>(); 编译报错:因为Test1是值类型约束,而object是引用类型Test1<int> t1 = new Test1<int>();t1.fun(123);// Test2<int> t2 = new Test2<int>(); 编译报错:因为Test2是引用类型约束,而int是值类型Test2<object> t2 = new Test2<object>();t2.fun(new Random());// Test3<A> t3 = new Test3<A>(); 编译报错:因为Test3是无参公共构造函数约束,而A没有公共无参构造函数Test3<B> t3 = new Test3<B>();t3.fun(new B());// Test4<Test1<int>> t4 = new Test4<Test1<int>>(); 编译报错:因为Test4是Test2或其子类约束,而Test1不是Test2或其子类Test4<Test2<object>> t4 = new Test4<Test2<object>>();t4.fun(new Test2<object>());// Test5<A> t5 = new Test5<A>(); 编译报错:因为Test5是ITest接口实现类约束,而A没有实现ITest接口Test5<C> t5 = new Test5<C>();t5.fun(new C());// Test6<C, E> t6 = new Test6<C, E>(); 编译报错:因为Test6是另一个泛型类或及其派生类约束,而C不是E或其派生类Test6<D, E> t6 = new Test6<D, E>();t6.fun<D, E>(new D());Test7<B> t7 = new Test7<B>();t7.fun(new B());}}// 值类型class Test1<T> where T : struct{public T value;public void fun<K>(K k) where K : struct{Console.WriteLine(k + "是值类型");}}// 引用类型class Test2<T> where T : class{public T value;public void fun<K>(K k) where K : class{Console.WriteLine(k + "是引用类型");}}// 存在公共无参构造函数class Test3<T> where T : new(){public T value;public void fun<K>(K k) where K : new(){Console.WriteLine(k + "有公共无参构造方法");}}class A{private int value;public A(int value){this.value = value;}}class B{public B() {}}class Test4<T> where T : Test2<object>{public T value;public void fun<K>(K k) where K : Test2<object>{Console.WriteLine(k + "是Test2类或其派生类");}}// 接口约束class Test5<T> where T : ITest{public T value;public void fun<K>(K k) where K : ITest{Console.WriteLine(k + "是ITest接口的派生类");}}interface ITest { }class C : ITest { }// 泛型类及其派生类约束class Test6<T, M> where T : M{public T value;public void fun<K, V>(K k) where K : V{Console.WriteLine(k + "是" + typeof(V) + "或其派生类");}}class E { }class D : E { }// 泛型有多个约束:使用逗号分隔class Test7<T> where T : class, new(){public T value;public void fun<K>(K k) where K : class, new(){Console.WriteLine(k + "是引用类型且有公共无参构造方法");}}
}
运行结果如下:
四、多个泛型有约束
using System;namespace GenericConstraints
{class Program{static void Main(string[] args){// Test<object> t1 = new Test<object>(); 编译报错:因为Test1是值类型约束,而object是引用类型Test1<int> t1 = new Test1<int>();t1.fun(123);// Test2<int> t2 = new Test2<int>(); 编译报错:因为Test2是引用类型约束,而int是值类型Test2<object> t2 = new Test2<object>();t2.fun(new Random());// Test3<A> t3 = new Test3<A>(); 编译报错:因为Test3是无参公共构造函数约束,而A没有公共无参构造函数Test3<B> t3 = new Test3<B>();t3.fun(new B());// Test4<Test1<int>> t4 = new Test4<Test1<int>>(); 编译报错:因为Test4是Test2或其子类约束,而Test1不是Test2或其子类Test4<Test2<object>> t4 = new Test4<Test2<object>>();t4.fun(new Test2<object>());// Test5<A> t5 = new Test5<A>(); 编译报错:因为Test5是ITest接口实现类约束,而A没有实现ITest接口Test5<C> t5 = new Test5<C>();t5.fun(new C());// Test6<C, E> t6 = new Test6<C, E>(); 编译报错:因为Test6是另一个泛型类或及其派生类约束,而C不是E或其派生类Test6<D, E> t6 = new Test6<D, E>();t6.fun<D, E>(new D());Test7<B> t7 = new Test7<B>();t7.fun(new B());Test8<int, object> t8 = new Test8<int, object>();t8.fun(666, "Hello World!");}}// 值类型class Test1<T> where T : struct{public T value;public void fun<K>(K k) where K : struct{Console.WriteLine(k + "是值类型");}}// 引用类型class Test2<T> where T : class{public T value;public void fun<K>(K k) where K : class{Console.WriteLine(k + "是引用类型");}}// 存在公共无参构造函数class Test3<T> where T : new(){public T value;public void fun<K>(K k) where K : new(){Console.WriteLine(k + "有公共无参构造方法");}}class A{private int value;public A(int value){this.value = value;}}class B{public B() {}}class Test4<T> where T : Test2<object>{public T value;public void fun<K>(K k) where K : Test2<object>{Console.WriteLine(k + "是Test2类或其派生类");}}// 接口约束class Test5<T> where T : ITest{public T value;public void fun<K>(K k) where K : ITest{Console.WriteLine(k + "是ITest接口的派生类");}}interface ITest { }class C : ITest { }// 泛型类及其派生类约束class Test6<T, M> where T : M{public T value;public void fun<K, V>(K k) where K : V{Console.WriteLine(k + "是" + typeof(V) + "或其派生类");}}class E { }class D : E { }// 泛型有多个约束:使用逗号分隔class Test7<T> where T : class, new(){public T value;public void fun<K>(K k) where K : class, new(){Console.WriteLine(k + "是引用类型且有公共无参构造方法");}}// 多个泛型有约束:多条where语句class Test8<T, M> where T : struct where M : class{public T value;public void fun<K, V>(K k, V v) where K : struct where V : class{Console.WriteLine(k + "是值类型且" + v + "是引用类型");}}
}
运行结果如下:
今天的学习就到这里了。感谢阅读。
再见!