一、泛型定义
允许编写一个可以与任何数据类型一起工作的类或方法
二、泛型类型
- 类:class 类名<占位字符>
- 函数:返回值类型 函数名<占位字符>(参数类型 参数1,...)
三、实例演示(类与函数)
1、创建一个数组类
class MyArray<T>//数组类
{
private T[] myarray;//数组定义
public int MyarrayLength//属性获取数组长度
{
get
{
return myarray.Length;
}
}
public MyArray(int size)//构造函数初始化数组长度
{
myarray = new T[size];
}
//通过下标获取数组数据
public T GetMyarrayByIndex(int index)
{
return myarray[index];
}
//数组赋值
public void SetMyarrayByindex(int index,T value)
{
myarray[index] = value;
}
}
2、在主函数中调用与使用,int类型
MyArray<int> intMyarray = new MyArray<int>(5);//实例化并调用构造函数初始化数组长度为5
for (int i = 0; i < intMyarray.MyarrayLength; i++)
{
intMyarray.SetMyarrayByindex(i, i * 2);//赋值
}
for (int i = 0; i < intMyarray.MyarrayLength; i++)
{
Console.WriteLine(intMyarray.GetMyarrayByIndex(i));//输出数组
}
3、string类型
MyArray<string> stringMyarray = new MyArray<string>(5);//实例化并调用构造函数初始化数组长度为5
for (int i = 0; i < stringMyarray.MyarrayLength; i++)
{
stringMyarray.SetMyarrayByindex(i, (i * 2).ToString());//赋值
}
for (int i = 0; i < stringMyarray.MyarrayLength; i++)
{
Console.WriteLine(stringMyarray.GetMyarrayByIndex(i));//输出数组
}
4、完整代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/*
泛型:允许编写一个可以与任何数据类型一起工作的类或方法
类:class 类名<占位字符>
函数:返回值类型 函数名<占位字符>(参数类型 参数1,...)
*/
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
MyArray<int> intMyarray = new MyArray<int>(5);//实例化并调用构造函数初始化数组长度为5
for (int i = 0; i < intMyarray.MyarrayLength; i++)
{
intMyarray.SetMyarrayByindex(i, i * 2);//赋值
}
for (int i = 0; i < intMyarray.MyarrayLength; i++)
{
Console.WriteLine(intMyarray.GetMyarrayByIndex(i));//输出数组
}
MyArray<string> stringMyarray = new MyArray<string>(5);//实例化并调用构造函数初始化数组长度为5
for (int i = 0; i < stringMyarray.MyarrayLength; i++)
{
stringMyarray.SetMyarrayByindex(i, (i * 2).ToString());//赋值
}
for (int i = 0; i < stringMyarray.MyarrayLength; i++)
{
Console.WriteLine(stringMyarray.GetMyarrayByIndex(i));//输出数组
}
}
}
class MyArray<T>//数组类
{
private T[] myarray;//数组定义
public int MyarrayLength//属性获取数组长度
{
get
{
return myarray.Length;
}
}
public MyArray(int size)//构造函数初始化数组长度
{
myarray = new T[size];
}
//通过下标获取数组数据
public T GetMyarrayByIndex(int index)
{
return myarray[index];
}
//数组赋值
public void SetMyarrayByindex(int index,T value)
{
myarray[index] = value;
}
}
}
四、泛型是一种增强程序功能的技术
- 最大限度的复用代码
- 泛型类、泛型函数、泛型接口、泛型委托、泛型事件
- 可以对泛型进行约束,从而访问特定的数据类型
- 泛型数据类型的类型信息可以利用反射在程序运行时获取
五、泛型委托
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
public delegate T numberChanger<T>(T num);//泛型委托声明
class Program
{
static void Main(string[] args)
{
Number number = new Number();
numberChanger<int> nc1 = new numberChanger<int>(number.AddNum);//int
Console.WriteLine(nc1(5));
numberChanger<double> nc2 = new numberChanger<double>(number.MulNum);//double
Console.WriteLine(nc2(5));
}
}
class Number
{
public int AddNum(int num)
{
return num += num;
}
public double MulNum(double num)
{
return num *= num;
}
}
}
六、约束
因为泛型的泛用性,我们一般需要约束其范围,关键字where
约束语法:
- 值类型:where T:struct (int、bool、byte、double等)
- 引用类型:where T:class (对象、字符串、委托、数组等)
- 必须存在无参构造函数:where T:new()
- 类的派生:where T:类名
- 接口的派生:where T:接口名
- 泛型派生:where T:U --另一个泛型
案例演示
1、值类型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//泛型类 加上值类型约束
Test1<int> t1 = new Test1<int>();
t1.value = 100;
//使用引用类型对象给值类型约束赋值,报错
//Test1<string> t2 = new Test1<string>();
//t2.value = "abc";
}
}
//泛型类 加上值类型约束 where T:struct
class Test1<T> where T:struct
{
public T value;
//泛型函数,加上值类型约束
public void TestMethod<K>() where K : struct
{
}
}
}
报错如下:
2、引用类型
与前面相反
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//使用值类型对象给引用类型约束赋值,报错
//Test1<int> t1 = new Test1<int>();
//t1.value = 100;
//泛型类 加上值类型约束
Test1<string> t2 = new Test1<string>();
t2.value = "abc";
}
}
//泛型类 加上引用类型约束 where T:class
class Test1<T> where T:class
{
public T value;
//泛型函数,加上引用类型约束
public void TestMethod<K>() where K : class
{
}
}
}
报错如下:
3、必须存在无参构造函数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//必须存在无参构造函数约束
Test1<Test2> t1 = new Test1<Test2>();
t1.TestMethod<Test2>();
//当不存在无参构造函数 报错
//Test1<Test3> t2 = new Test1<Test3>();
//t2.TestMethod<Test3>();
}
}
//泛型类 必须存在无参构造函数 where T:new()
class Test1<T> where T : new()
{
//泛型函数,加上必须存在无参构造函数约束
public void TestMethod<K>() where K : new()
{
}
}
class Test2
{
}
class Test3
{
public Test3(int a)//有参构造函数
{
}
}
}
报错如下:
4、类的派生
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//类名作为约束
Test1<Test2> t1 = new Test1<Test2>();
Test1<Test3> t2 = new Test1<Test3>();
//使用时,只能使用该类本身或者该类的派生类,否则报错
//Test1<Test4> t3 = new Test1<Test4>();
}
}
//泛型类 加上某个类名作为约束,代表T类型必须是该类本身或者是该类的派生类
class Test1<T> where T : Test2
{
}
class Test2
{
}
class Test3 : Test2
{
}
class Test4
{
}
}
报错如下:
5、接口的派生
和前面类似
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//接口名作为约束
Test1<ITest2> t1 = new Test1<ITest2>();
Test1<ITest3> t2 = new Test1<ITest3>();
//使用时,只能使用该接口本身或者该接口的派生类,否则报错
//Test1<ITest4> t3 = new Test1<ITest4>();
}
}
//泛型类 加上某个接口名作为约束,代表T类型必须是该接口本身或者是该接口的派生类
class Test1<T> where T : ITest2
{
}
interface ITest2
{
}
interface ITest3 : ITest2
{
}
interface ITest4
{
}
}
报错如下:
6、泛型派生
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//泛型作为约束
Test1<Test3, ITest2> t1 = new Test1<Test3, ITest2>();
//使用时,只能使用该泛型(U)本身或者该泛型(U)的派生类,否则报错
//Test1<Test3, Test4> t2 = new Test1<Test3, Test4>();
}
}
//泛型类 加上另一个泛型占位符作为约束,代表T类型必须和U类型是同一类型或者是他的派生类型
class Test1<T,U> where T : U
{
}
interface ITest2
{
}
class Test3 : ITest2
{
}
class Test4
{
}
}
报错如下:
7、多个约束组合
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//多个约束条件使用
Test1<Test2> t1 = new Test1<Test2>();
//当有多个约束条件时,那么需要都满足
//Test1<Test3> t2 = new Test1<Test3>();
}
}
//泛型类 多个约束组合
class Test1<T> where T : class, new()
{
}
class Test2
{
}
class Test3
{
public Test3(int a)
{
}
}
}
报错如下: