一、什么是泛型?
泛型(Generic)?允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。换句话说,泛型允许您编写一个可以与任何数据类型一起工作的类或方法。
您可以通过数据类型的替代参数编写类或方法的规范。当编译器遇到类的构造函数或方法的函数调用时,它会生成代码来处理指定的数据类型。
?官方描述总是很抽象的,在Unity中List<T>、GetComponent<T> 、Dictionary<TKey,Tvalue>和KeyValue<T,T>这些都是我们常用的泛型,其中T、Tkey、Tvalue起到了占位符的作用。里面可以书写任意字符(如:A、B、C这都可以),规范化默认写为T。
怕有些小伙伴不懂什么是占位符,简单说一下,占位符顾名思义就是帮你的字符占一个位置,举个我们常用的占位符例子:Console.WriteLine("我是占位符: {0}, 我是占位符: {1}", "0", "1"); 这里{0},{1}就是占位符,替0,1占了一个位置。
?泛型的使用:
1.泛型的简单使用 :定义一个动物类,age年龄定义为泛型,这样的好处是我们在实例化不同类时,根据需要可以重新定义age的参数类型,这样能大大提高类的复用性。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenericityTest : MonoBehaviour
{
void Start()
{
//定义string类型
Animal<string> dog = new Animal<string>("dog","5");
Debug.Log(dog.name+"年龄:"+dog.age);
//定义int类型
Animal<int> cat = new Animal<int>("cat",3);
Debug.Log(cat.name + "年龄:" + cat.age);
}
}
// 动物类
public class Animal<T>
{
public string name;
public T age;
public Animal(string _name,T _age)
{
name = _name;
age = _age;
}
}
2.如果我们动物的名称类型也需要开放出来怎么办?
在Animal类中在添加一个泛型<T,K>,即可
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenericityTest : MonoBehaviour
{
void Start()
{
Animal<string,string> dog = new Animal<string,string>("dog","5");
Debug.Log(dog.name+"年龄:"+dog.age);
Animal<string,int> cat = new Animal<string,int>("cat",3);
Debug.Log(cat.name + "年龄:" + cat.age);
}
}
// 动物类
public class Animal<T,K>
{
public T name;
public K age;
public Animal(T _name,K _age)
{
name = _name;
age = _age;
}
}
3.泛型约束:
泛型各类约束:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters
①where T:struct? 限定当前参数类型必须是值类型
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenericityTest : MonoBehaviour
{
void Start()
{
BaseData dog = new BaseData() {name="dog",age=5 };
Animal<BaseData> animal = new Animal<BaseData>(dog);
animal.OutPut();
}
}
//结构约束
public class Animal<T> where T : struct
{
BaseData baseData;
public Animal(BaseData _baseData)
{
baseData = _baseData;
}
public void OutPut()
{
Debug.Log(baseData.name+" "+ baseData.age);
}
}
//基础属性类
public struct BaseData
{
public string name;
public int age;
}
②where T:class?? 限定当前类型参数类型必须是引用类型,也可用于类、接口、委托和数组
类约束:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//类约束
public class GenericityTest : MonoBehaviour
{
void Start()
{
BaseData dogBaseData = new BaseData("dog",5);
Animal<BaseData> dog = new Animal<BaseData>(dogBaseData);
Debug.Log(dog.baseData.name + "年龄:" + dog.baseData.age);
BaseData catBaseData = new BaseData("cat", 3);
Animal<BaseData> cat = new Animal<BaseData>(catBaseData);
Debug.Log(cat.baseData.name + "年龄:" + cat.baseData.age);
}
void Update()
{
}
}
// 动物类 Where T:BaseData 约束T只能是BaseData类型
public class Animal<T> where T:BaseData
{
public T baseData;
public Animal(T _baseData)
{
baseData = _baseData;
}
}
public class BaseData
{
public string name;
public int age;
public BaseData(string _name,int _age)
{
name = _name;
age = _age;
}
}
接口约束:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//接口约束
public class GenericityTest : MonoBehaviour
{
public BaseDataInterface<BaseData> animal;
void Start()
{
BaseData dogbaseData = new BaseData() { name = "dog", age = 5 };
animal = new Animal();
animal.OutPut(dogbaseData);
}
}
//定义动物类 继承接口
public class Animal : BaseDataInterface<BaseData>
{
public void OutPut(BaseData dogbaseData)
{
Debug.Log(dogbaseData.name + " "+ dogbaseData.age);
}
}
//接口约束 引用参数
public interface BaseDataInterface<T> where T : BaseData
{
void OutPut(T baseData);
}
//基础属性类
public class BaseData
{
public string name;
public int age;
}
委托约束:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//委托约束
public delegate void BaseData<T, K>(T name, K age);
//public delegate void BaseData(string name, int age);
public class GenericityTest : MonoBehaviour
{
BaseData<string, int> baseData;
void Start()
{
baseData += Output;
baseData("dog",5);
}
void Output(string name,int age)
{
Debug.Log("我是"+name+", 年龄:"+age);
}
}
数组约束:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//数组约束
public class GenericityTest : MonoBehaviour
{
BaseData[] array;
void Start()
{
//给数组赋值
BaseData basedata1 = new BaseData { name = "dog", age = 5 };
BaseData basedata2 = new BaseData { name = "cat", age = 3 };
array[0] = basedata1;
array[1] = basedata2;
Animal<BaseData> animal = new Animal<BaseData>() { m_array = array };
animal.OutPut();
}
}
//数组泛型约束
public class Animal<T> where T : BaseData
{
public T[] m_array;
public void OutPut()
{
foreach (T item in m_array)
{
Debug.Log(item.name + " " + item.age);
}
}
}
//基础属性类
public class BaseData
{
public string name;
public int age;
}
③where T:new() 限定当前参数类型必须有一个无参构造器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenericityTest : MonoBehaviour
{
void Start()
{
BaseData dog = new BaseData("dog", 5);
Animal<BaseData> animal = new Animal<BaseData>();
animal.OutPut(dog);
}
}
//数组泛型约束
public class Animal<T> where T : new()
{
public void OutPut(BaseData baseData)
{
Debug.Log(baseData.name+" "+ baseData.age);
}
}
//基础属性类
public class BaseData
{
public string name;
public int age;
//class 如果没有构造时 默认为无参构造函数,如果书写了有参构造函数 必须要在写一个无参函数否则where T :new() 报错
public BaseData()
{
}
public BaseData(string _name, int _age)
{
name = _name;
age = _age;
}
}
|