【C#基础】泛型的概念?有什么例子?在游戏中有什么可以使用的地方?

概念

chatGpt来为我们讲解。

C#中,泛型是一种允许开发人员编写可重用代码,可以处理多种数据类型的特性。

使用泛型,可以创建类、方法、接口和委托这种不属于任何特定数据的类型,但可以处理满足某些约束条件的任何数据类型。

主要优点:

  • 让代码更加通用。

  • 在编译时提供类型安全性,也可以避免装箱和拆箱的操作,从而提高性能

  • 我们没必要用转换了,代码更简洁了

以下是C#中泛型类的示例:

public class MyGenericClass<T> { 
    private T myVariable; 
    public MyGenericClass(T value) { 
        myVariable = value; 
    } 
    public T GetValue() { return myVariable; } 
} 

在此示例中,使用类型参数T定义了MyGenericClass类。构造函数接受类型为T的值并将其存储在私有变量中,GetValue方法返回存储的值。

要使用特定的数据类型使用此类,可以在创建类的实例时指定数据类型,如下所示:

MyGenericClass<int> myIntClass = new MyGenericClass<int>(42); 
int myIntValue = myIntClass.GetValue(); 

在此示例中,使用类型参数为int创建了MyGenericClass类的myIntClass实例,GetValue方法返回一个int值。

创建方式

接下来我们分别讲讲有那些写法,可供我们需要的时候参考。

单个参数类型T

使用泛型类型T来创建的数组可以随意指定,这样做的好处是可以重复使用CreateArray方法来创建任何数据类型的数组,而不需要为每个数据类型编写不同的代码。

public class TestingGenerics1 : MonoBehaviour
{
    private void Start()
    {
        int[] intArray = CreateArray<int>(5, 6);
        Debug.Log(intArray.Length + " " + intArray[0] + " " + intArray[1]);
        Debug.Log(intArray.GetType());//int32

        Debug.Log(CreateArray<string>("a","b").GetType());//string
    }
	//为任何数据类型创建数组,接受由泛型类型T定义的两个参数
    private T[] CreateArray<T>(T first,T second)
    {
        return new T[] { first, second };
    }
}

多个参数类型T

public class TestingGenerics1 : MonoBehaviour
{
    private void Start()
    {
        CreateMultiArray<int,string>(5, "6");
    }

    private void CreateMultiArray<T1,T2>(T1 first,T2 second)
    {
        Debug.Log(first.GetType());
        Debug.Log(second.GetType());
    }
}

在这里插入图片描述

泛型委托和预定义委托的类型

public class TestingGenerics1 : MonoBehaviour
{
	//两个参数,不返回值
    private delegate void MyActionDelegate<T1, T2>(T1 t1, T2 t2);
    private Action<int,string> action;
	//一个参数类型T1,返回类型为TResult的值
    private delegate TResult MyFuncDelegate<T1, TResult>(T1 t1);
    private Func<int,bool> func;
}

泛型和接口

目标

  • 创建一个可重复使用的MyClass类,它可以使用任何实现了IEnemy接口的类型作为其类型参数T

好处

  • 提高代码的可重用性和可维护性。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestingGenerics1 : MonoBehaviour
{
    private void Start()
    {
    //创建了两个MyClass类的实例,分别传递了一个EnemyMinion和一个EnemyArcher类型的对象。
        MyClass<EnemyMinion> myClass = new MyClass<EnemyMinion>(new EnemyMinion());
        MyClass<EnemyArcher> myClassArcher = new MyClass<EnemyArcher>(new EnemyArcher());
    }
}
//MyClass类是一个泛型类,其类型参数T必须是实现了IEnemy接口的类型。
public class MyClass<T> where T : IEnemy
{
	//包含一个公共字段value,它存储传递给构造函数的值
    public T value;
    //并在构造函数中调用了这个值的Damage()方法。
    public MyClass(T value)
    {
        value.Damage();
    }
    private T[] PersonalAction(T first, T second){...}
}
//IEnemy接口定义了一个方法Damage(),表示敌人受到攻击时所需执行的动作。
public interface IEnemy
{
    void Damage();
}
//EnemyMinion和EnemyArcher类都实现了IEnemy接口,并分别定义了它们自己的Damage()方法。
public class EnemyMinion : IEnemy
{
    public void Damage()
    {
        Debug.Log("EnemyMinion.Damage()");
    }
}

public class EnemyArcher : IEnemy
{
    public void Damage()
    {
        Debug.Log("EnemyArcher.Damage()");
    }
}

在这里插入图片描述

增强灵活性和重用性

public class TestingGenerics1 : MonoBehaviour
{
    private void Start()
    {
        MyClass<EnemyMinion> myClass = new MyClass<EnemyMinion>(new EnemyMinion());
        MyClass<EnemyArcher> myClassArcher = new MyClass<EnemyArcher>(new EnemyArcher());
    }
}
/*不同点1:添加额外约束*/
//要求类型参数T必须是一个类(即引用类型),必须实现IEnemy<T>接口,且必须有一个无参数构造函数。
public class MyClass<T> where T : class,IEnemy<int>,new()
{
    public T value;
    public MyClass(T value)
    {
        value.Damage(0);
    }
    private T[] CreateArray(T first, T second)
    {
        return new T[] { first, second };
    }
}

public interface IEnemy<T>
{
/*不同点2:Damage方法的参数类型变为了T类型,即泛型类型*/
//这意味着,敌人类可以使用不同的数据类型作为受到攻击时所需执行的参数类型。
    void Damage(T t);
}

public class EnemyMinion : IEnemy<int>
{
	//与IEnemy<T>接口的定义相匹配
    public void Damage(int i)
    {
        Debug.Log("EnemyMinion.Damage()"+i);
    }
}

public class EnemyArcher : IEnemy<int>
{
    public void Damage(int i)
    {
        Debug.Log("EnemyArcher.Damage()"+i);
    }
}

在游戏中的使用例子

场景:

你现在要创建一个角色,而我们知道创建一个角色前,我们是可以选定角色的职业的,假设我们要弄一个简易的游戏角色生成器,而你要创建两种不同类型的角色:saber、assassin,我们会怎么做?

请添加图片描述

这次我就不写没学过泛型概念的一般人是怎么想的了

1.创建一个基类Role,表示共同属性

// 定义一个角色类,包含姓名和职业两个属性
public class Role
{
    public string Name { get; set; }
    public string Job { get; set; }
    public int HP { get; set; }
    public int MP { get; set; }

    public virtual void Attack()
    {
        Debug.Log(this.Name + " attacks with a normal attack.");
    }
}

2.为了表示职业特殊,角色的武器不同

// 定义 Saber 类和 Assassin 类,继承自角色类
public class Saber : Role {
    //重载
    public override void Attack()
    {
        Debug.Log(this.Name +" is "+ this.Job +" attacks with a sword. " +
            "\n her HP:"+this.HP+"MP:"+this.MP);
    }
}
public class Assassin : Role {
    public override void Attack()
    {
        Debug.Log(this.Name + " is " + this.Job + " attacks with a dagger. " +
            "\n his HP:" + this.HP + "MP:" + this.MP);
    }
}

3.创建一个简易函数,表示角色生成器

// 定义一个角色生成器类,包含一个泛型方法,用于生成指定职业的角色
public class RoleGenerator
{
    public T GenerateRole<T>(string name,int HP,int MP) where T : Role, new()
    {
        T role = new T();
        role.Name = name;
        role.HP = HP;
        role.MP = MP;
        if (typeof(T) == typeof(Saber))
        {
            role.Job = "Saber";
        }
        else if (typeof(T) == typeof(Assassin))
        {
            role.Job = "Assassin";
        }
        return role;
    }
}

4. 测试

public class TestingGenerics1 : MonoBehaviour
{
    private void Start()
    {
        // 创建角色生成器实例
        RoleGenerator generator = new RoleGenerator();

        // 生成一个名为 "Artoria" 的 Saber 类型的角色
        Saber saber = generator.GenerateRole<Saber>("呆毛",100,20);
        saber.Attack();

        // 生成一个名为 "Jack" 的 Assassin 类型的角色
        Assassin assassin = generator.GenerateRole<Assassin>("山中老人",200,10);
        assassin.Attack();
    }
}

在这里插入图片描述

总结

C#中的泛型,是一种强大的功能,可以创建一个特定的类,可以与任何类型一起使用。

本文解释了如何编写一个类或函数,而不定义任何特定类型,并在使用类或函数时传递类型。

此外还涵盖了如何在委托中使用泛型,向泛型添加约束以及在接口中使用泛型。

提供了使用泛型创建网格系统、创建返回包含任何类型元素的数组的函数以及创建可以使用泛型类型的类的示例。

题外话

本来想让chatGPT顺便提供一些在unity游戏开发的使用场景,但是它回答的实在是听君一席话,如听一席话,我还是不发了,免得有像我一样的小白看不懂。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/5276.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

手机银行评测系列:北京银行“京彩生活”7.0从用户视角出发,实现沉浸式体验重塑

易观&#xff1a;2023年3月28日&#xff0c;北京银行发布“京彩生活”APP 7.0版本&#xff0c;从旅程再造、特色金融、场景生态、平台联动、协同经营、体验管理和安全守护七大方面全面升级&#xff0c;从用户视角出发&#xff0c;重塑用户旅程&#xff0c;简化操作流程&#xf…

PDF Extra(安卓)

首先&#xff0c;软件是一个一体化的扫描仪和编辑器&#xff0c;工具主要包含有编辑&#xff0c;创建&#xff0c;转换&#xff0c;阅读和查看&#xff0c;其它等等多个功能类型。 编辑里面包含有编辑文本和图像&#xff0c;填写并签署&#xff0c;组织页面&#xff0c;压缩&am…

PLG 基础概念和关键点

什么是 PLGPLG 是 Product Led Growth 的缩写&#xff0c;常翻译为产品增长或产品主导型增长。这个概念最早是风投公司 OpenView 2016年提出的。定义&#xff1a;PLG 是一个聚焦终端用户的增长模型&#xff0c;依赖于产品自身作为获取、转化、扩展客户的核心动力。• 以产品来驱…

入行软件测试7年,才知道原来字节跳动这么容易进

当前就业环境&#xff0c;裁员、失业消息满天飞&#xff0c;好像有一份工作就不错了&#xff0c;更别说高薪了。其实这只是一方面&#xff0c;而另一方面&#xff0c;各大企业依然求贤若渴&#xff0c;高技术人才依然紧缺&#xff0c;只要你技术过硬&#xff0c;拿个年薪50w不是…

vue3快速上手

Vue3快速上手 1.Vue3简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff09;耗时2年多、2600次提交、30个RFC、600次PR、99位贡献者github上的tags地址&#xff1a;https://github.com/vuejs/vue-next/release…

核心 Android 调节音量的过程

核心 Android 系统提供的调节音量的方法 核心 Android 系统提供了多种调节音量的方法&#xff0c;这些方法主要包括如下这些。 如在 Android Automotive 调节音量的过程 中我们看到的&#xff0c;CarAudioService 最终在 CarAudioDeviceInfo 中 (packages/services/Car/servi…

开源DataX集成可视化项目Datax-Web的使用

上一篇文章我们已经搭建好了 Datax-Web 后台&#xff0c;这篇文章我们具体讲一下如何通过Datax-Web来配置&#xff0c;同步MySQL数据库。 目标 MySql数据库全量同步 1.执行器配置 1、"调度中心OnLine:"右侧显示在线的"调度中心"列表, 任务执行结束后, 将会…

红黑树、B树以及B+树及应用

目录 一.二叉查找树(二叉搜索树&#xff0c;BST) 1.1查找操作 1.2插入操作 1.3删除操作 1.4支持重复数据的二叉查找树 1.5二叉查找树的性能分析 二.平衡二叉查找树 2.1定义 2.2红黑树 2.3为什么红黑树这么受欢迎 三.哈希表为什么不能替代二叉查找树 四.MySQL数据库索…

基于springboot实现学生综合成绩测评系统【源码】分享

基于springboot实现学生综合成绩测评系统演示开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包…

机器学习模型部署PMML

PMML 简介 预测模型标记语言PMML&#xff08;Predictive Model Markup Language&#xff09;是一套与平台和环境无关的模型表示语言&#xff0c;是目前表示机器学习模型的实际标准。从2001年发布的PMML1.1&#xff0c;到2019年最新4.4&#xff0c;PMML标准已经由最初的6个模型…

python+vue高校教务选课管理系统django

1. 简介&#xff1a;学生选课系统是学校管理中不可缺少的一部分&#xff0c;它将方便教师发布课程信息、学生浏览课程信息和选课&#xff0c;为两者提供充分的课程信息和方便的查询手段&#xff0c;极大的提高人事劳资管理的效率。 2. 功能&#xff1a;实现基于B/S架构学…

使用SpringBoot+JWT+MybatisPlus实现简单的登陆状态验证

文章目录前言一、JWT是什么&#xff1f;二、使用步骤1.创建项目&#xff0c;导入依赖&#xff0c;配置、引入工具类2.编写LoginController和UserController3.编写跨域拦截器和token验证拦截器4.全局拦截器配置三、业务逻辑四、测试总结前言 登陆功能是每个系统的最基本功能&am…

国内怎么注册chatgpt4-gptchat账号用多久

GPT &#xff08;Generative Pre-trained Transformer&#xff09;是一种强大的自然语言处理人工智能技术&#xff0c;可以用于各种语言任务&#xff0c;包括机器翻译、问答系统、自然语言生成等。作为一种技术&#xff0c;GPT并没有一个固定的玩法&#xff0c;但可以通过各种工…

VMware(虚拟机)安装CentOS7并且连接XShell教程

VMware&#xff08;虚拟机&#xff09;安装CentOS7 安装准备&#xff08;本文安装Centos7.6版本&#xff09; Centos7.6下载地址 创建 选择自定义 下一步默认 选择稍后安装 选择好下一步 修改下一步 根据自己的需求修改 虚拟机内存分配默认即可 先用默认后面…

【spring boot】在Java中操作缓存:

文章目录一、Jedis二、Spring Data Redis&#xff08;常用&#xff09;【1】pom.xml【2】application.yml【3】RedisConfig【4】RuiJiWaiMaiApplicationTests三、Spring Cache【1】常用注解&#xff1a;【2】使用案例【3】底层不使用redis&#xff0c;重启服务&#xff0c;内存…

两句话,ChatGPT帮我写一个打飞机的游戏

大家好&#xff0c;我是全村的希望今天的主题是让 chatGPT 来帮我们写一个打飞机的游戏记得我刚学 Python 的时候&#xff0c;看的那本很经典的入门书《Python 编程&#xff1a;从入门到实践》&#xff0c;里面就有小项目就是教你编写一个打飞机的游戏我那时候是对着书一个一个…

4.8 Beijing Rust Meetup | Call For Presenters

如果你有兴趣参与探讨Rust作为一种强调性能、安全和并发性的编程语言的各种应用、实践和无限可能性的头脑风暴&#xff0c;就一定不能错过这场来自达坦科技、南京大学、CloudWeGo、华为等技术专家带来的关于Rust编程语言相关应用的线下Meetup。我们的主题是Rust &#x1f4a1;X…

优维科技联合广发证券发起「CD持续交付一期项目复盘会」

2023年3月16日&#xff0c;由优维科技联合广发证券共同发起的「广发证券CD持续交付一期项目复盘会」在广发总部大厦闭幕。 复盘目的 为了对广发证券CD持续交付一期项目的总体执行请看落实“回头看”方阵&#xff0c;充分挖掘项目的落地价值&#xff0c;总结项目未来可持续性开…

基于springboot实现广场舞团管理系统演【附项目源码】

基于springboot实现广场舞团管理系统演开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#…

【OS面试】说说你对IO多路复用的理解

面试官&#xff1a; 说说你对IO多路复用的理解&#xff1f; 我&#xff1a; IO多路复用是一种高效地管理多个文件描述符&#xff08;FD&#xff09;的方式&#xff0c;它允许同时监听多个IO事件并在有事件发生时立即响应。 在传统的IO编程中&#xff0c;每个socket连接都需要…
最新文章