59、C编程中的协程、属性与位运算深入解析

C#编程中的协程、属性与位运算深入解析

协程处理与属性应用

在编程里,当使用LINQ语句筛选并选定标记方法后,会为每个方法创建一个新的协程。具体而言,在 foreach 循环中会出现 updater() 内联函数,这意味着对于类中的每个 updateMethod 实例,都会创建一个新的 IEnumerator 函数。这些函数的数据会被存储在 List<IEnumerator> 中。

要获取延迟值,可以使用 method.GetCustomAttribute() 函数来获取函数标记属性中的延迟值,然后将该值添加到 updater() 函数 while 循环里的 yield return WaitForSeconds 函数中。完成设置后,将 Updater() 添加到 routineList 。当 updateMethods foreach 循环结束后,会遍历 routineList 中的所有项并启动协程,最终会在Unity控制台窗口中显示“Got Updated”和“Also Got Updated”,“Got Updated”每秒显示两次,“Also Got Updated”每三秒显示一次。

通过存储 routineList ,还能停止协程,这让系统更加健壮。保留协程的好处是,在需要时可以重新启动它们,这在切换场景或暂停游戏等情况下非常实用。

属性可以应用于类、函数和变量。在声明新的属性类时,有多种选项可供选择。可以使用按位运算符 | 添加额外的 AttributeTargets 来设置多个标志。

自定义属性能简化许多任务。例如,带有时间延迟的 Update 属性 [UpdateAttribute (3.0f)] 可让函数按自身节奏更新,并非所有函数都需要在每一帧开始时更新。每个怪物的行为部分可以在不同的时间值进行更新,聪明、快速的怪物更新频率可高于迟钝、缓慢的怪物。若要复活角色,可能需要将各种属性重置为默认值,使用 [DefaultAttribute(int restoredAmount)] 属性可自动完成这项工作,只需获取所有需要恢复的字段并将其恢复到指定的恢复量。自定义属性为函数或变量附加重要信息提供了一个易于阅读的系统。

位运算数学基础

位运算与常规数学运算有所不同。在计算机的二进制世界中,将10变为 -10不能简单地用10乘以 -1。以4位二进制数的半字节为例,无符号半字节的最大值是1111(即15),而有符号半字节的范围是 -8到7(即1000到0111)。

二进制数的范围是从0到一个上限,通常以十六进制形式呈现,在网页颜色设置中经常会遇到。在十进制中,从0数到9后,需要增加一位来表示10;而计算机计数时使用16(即一个半字节),用字母来表示额外的数字,计数顺序为0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f。计算机从0数到255需要8位二进制数,若使用两个半字节则可用两位十六进制数表示。

在C#中,使用前缀 0x 表示十六进制数,例如 0x01 表示十进制的1, ff 表示十进制的255。有符号字节( sbyte )可以表示负数,如 -0x80 表示十进制的 -128。若给 sbyte 赋值超出范围,会出现错误提示。

int 类型有更大的范围,长度为8个半字节(即8位十六进制数),最大值是 0x7fffffff ,也可通过 int.MaxValue 访问。较小的值(如 0xff )可以赋值给 int

按位取反运算符 ~ 用于处理 int 值。若使用 byte b = 0x01; ~b 操作时C#会自动将 byte 类型提升为 int 类型。该运算符会对二进制位进行取反操作,例如对 0001 应用 ~ 运算符会得到 1110 。使用按位运算将 int 从10变为 -10的方法是取反加1,这种方法比乘法运算更快,在一些优化的C++代码中经常使用。

计算机CPU内部没有直接的 + - 电路,加法和减法都是通过位运算符实现的。以7 + 3为例,在半字节中,7表示为1110,3表示为1100,相加结果为1010(即10)。按位加法的过程如下:

1. 首先,使用`a & b`找出两个数中都为1的位,即需要进位的位,如`0111 & 0011 = 0011`。
2. 然后,使用`a ^ b`找出两个数中不同的位,如`0111 ^ 0011 = 0100`。
3. 接着,将进位的位左移一位`int s = c << 1;`。
4. 重复上述步骤,直到进位为0。

减法可通过将减数取反加1后与被减数相加来实现,即使用之前的按位取反方法得到负数,再使用按位加法函数。

位左移运算符 << 可用于乘以2,如 4 << 1 = 8 。乘法可以通过多次左移和加法实现,例如7 * 3可表示为 (7 * 2) + 7 。除法可简化为从被除数中多次减去除数。

位运算还有一些实用技巧。例如,使用 n & 1 == 1 判断一个 int 是否为奇数比使用 n % 2 == 0 更快;通过 (someNumber & (1<<31)) != 0 可以判断一个数是否为负数。不过,并非所有位运算技巧都比常规数学函数更快,但了解位运算的工作原理很有趣。

项目架构与组织策略

在构建游戏项目时,将C#文件按任务分开非常重要。这样做的好处是,任务的添加或合并会更加容易,在团队协作中也能减少文件合并的次数。如果每个类的功能范围较窄,只处理少数相关任务,那么查找和修复错误会更方便,调试也会更高效。

当独自工作时,对代码库的掌控相对容易,但在团队协作中,每个人应专注于代码库中较小、更专业的部分。将每个任务放在单独的文件中,可减少多人同时修改文件的情况,降低使用版本控制系统(如Git)时的合并冲突。

在规划项目结构时,在 Assets 根目录下应为游戏公司或游戏标题创建一个目录,该目录可作为项目中最通用的函数和类的容器。

以下是一个简单的流程图,展示了按位加法的过程:

graph TD;
    A[开始] --> B[计算a & b得到进位c];
    B --> C[计算a ^ b得到结果r];
    C --> D[c是否为0];
    D -- 否 --> E[c左移一位];
    E --> F[a = r, b = c];
    F --> B;
    D -- 是 --> G[结束];

以下是按位加法和减法的操作步骤总结:
| 操作 | 步骤 |
| ---- | ---- |
| 按位加法 | 1. 计算 a & b 得到进位 c ;2. 计算 a ^ b 得到结果 r ;3. 若 c 不为0,将 c 左移一位,更新 a = r b = c ,重复步骤1和2;4. 若 c 为0,结束。 |
| 按位减法 | 1. 将减数 b 按位取反加1得到负数;2. 使用按位加法函数将被减数 a 和负数相加。 |

总之,这些编程概念虽然较为底层,但为理解C#提供了重要基础。掌握它们有助于创建更复杂、有趣的游戏玩法场景,同时在数据处理等方面也有广泛应用。

C#编程中的协程、属性与位运算深入解析(续)

位运算在实际编程中的应用拓展

位运算在实际编程中有着广泛的应用,除了前面提到的基本数学运算,还能用于解决一些特定的问题。例如,在判断两个数的正负性时,可以使用位运算来提高效率。

若要判断两个数a和b是否同号,可以使用 (a ^ b) >= 0 来实现。如果结果为真,则a和b同号;否则,a和b异号。

这种方法利用了异或运算的特性,当两个数同号时,它们的符号位相同,异或结果的符号位为0;当两个数异号时,它们的符号位不同,异或结果的符号位为1。

另外,位运算还可以用于权限管理。假设我们有多个权限,每个权限用一个二进制位表示,那么可以通过位运算来组合和检查权限。

例如,有三个权限:读权限(用二进制位 001 表示)、写权限(用二进制位 010 表示)和执行权限(用二进制位 100 表示)。
若要检查一个用户是否具有读和写权限,可以将用户的权限值与 001 | 010 进行按位与运算,如果结果等于 001 | 010,则表示用户具有这两个权限。

以下是一个简单的权限管理示例代码:

// 定义权限常量
const int READ_PERMISSION = 0x01;
const int WRITE_PERMISSION = 0x02;
const int EXECUTE_PERMISSION = 0x04;

// 用户权限值
int userPermissions = READ_PERMISSION | WRITE_PERMISSION;

// 检查用户是否具有读和写权限
bool hasReadAndWrite = (userPermissions & (READ_PERMISSION | WRITE_PERMISSION)) == (READ_PERMISSION | WRITE_PERMISSION);
项目架构的进一步优化

在项目架构方面,除了将C#文件按任务分开,还可以使用命名空间来进一步组织代码。命名空间可以将相关的类和函数分组,避免命名冲突,提高代码的可读性和可维护性。

Assets 根目录下的游戏公司或游戏标题目录中,可以创建不同的子目录来存放不同功能模块的代码。例如,可以创建一个 Scripts 目录来存放所有的脚本文件,再在 Scripts 目录下创建 Gameplay UI Network 等子目录,分别存放游戏玩法、用户界面和网络相关的代码。

同时,使用接口和抽象类可以提高代码的灵活性和可扩展性。接口定义了一组方法的签名,实现该接口的类必须实现这些方法。抽象类则可以包含抽象方法和具体方法,继承抽象类的子类必须实现抽象方法。

以下是一个简单的接口和抽象类的示例:

// 定义一个接口
interface IAttackable
{
    void Attack();
}

// 定义一个抽象类
abstract class Character
{
    public string Name { get; set; }

    public abstract void Move();

    public void Speak()
    {
        Console.WriteLine($"{Name} is speaking.");
    }
}

// 实现接口和继承抽象类的具体类
class Warrior : Character, IAttackable
{
    public override void Move()
    {
        Console.WriteLine($"{Name} is running.");
    }

    public void Attack()
    {
        Console.WriteLine($"{Name} is attacking with a sword.");
    }
}
总结与展望

通过对协程、属性、位运算和项目架构的学习,我们了解到这些知识在C#编程中的重要性。协程可以实现异步操作,让程序在等待某些操作完成时继续执行其他任务;属性可以为类、函数和变量附加额外的信息,简化编程任务;位运算则提供了一种高效的计算方式,在底层编程和性能优化方面有着重要的应用;合理的项目架构可以提高代码的可维护性和可扩展性,便于团队协作开发。

在未来的编程实践中,我们可以进一步探索这些知识的应用场景,结合实际需求,灵活运用这些技术来解决问题。例如,在开发游戏时,可以使用协程来实现怪物的行为逻辑,使用属性来管理角色的属性和技能,使用位运算来优化游戏的性能,使用合理的项目架构来组织游戏的代码。

以下是一个总结表格,展示了本文介绍的主要知识点及其应用场景:
| 知识点 | 应用场景 |
| ---- | ---- |
| 协程 | 异步操作,如怪物行为逻辑、资源加载等 |
| 属性 | 函数定时更新、角色属性管理等 |
| 位运算 | 数学计算、权限管理、性能优化等 |
| 项目架构 | 团队协作开发、代码维护和扩展等 |

同时,为了更好地理解这些知识点之间的关系,我们可以用一个流程图来展示:

graph LR;
    A[协程] --> B[游戏开发];
    C[属性] --> B;
    D[位运算] --> B;
    E[项目架构] --> B;
    B --> F[提高游戏性能和可维护性];

希望本文能为读者在C#编程方面提供一些有用的参考和启示,帮助读者更好地掌握这些技术,开发出更加优秀的项目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值