C#中的相等比较及在游戏中的应用-新闻详情

C#中的相等比较及在游戏中的应用


发布时间:2017-10-31责任编辑:朱明 浏览:899


当我们在编写程序时,经常会遇到比较两个变量(对象)大小的情况,亦或是从某个集合中查找某个元素的情况。这时,便会用到对象间相等比较的处理。在C#中,相等比较划分为引用相等性与值相等性两种情况。

引用相等性

引用相等性指两个对象均引用内存中的同一基础对象。引用相等可以通过简单的赋值来实现,示例代码如下所示:

1.png

在上述代码中,我们使用了ReferenceEquals方法来确定两个对象是否引用同一对象。需要注意的是,引用相等性的判断仅适用于引用类型的对象。因为在将值类型的实例赋给变量时将会产生值类型的副本,因此值类型的对象不具有引用相等性。因此,永远不会有两个未装箱的值类型对象引用内存中的同一位置(基础对象)。此外,如果使用ReferenceEquals方法比较两个值类型,结果将始终为false。因为比较的过程会将两个值类型变量分别装箱到单独的引用类型对象中。

值相等性

值相等性指两个对象包含相同的一个或多个值。对于基元类型,针对值相等性的测试简单明了。可以使用 == 运算符进行比较。但对于大多数其他类型,针对值相等性的测试较为复杂,这也是我们接下来着重要说的。

首先,如何确定在定义类或结构时,我们为类型创建值相等性的自定义处理是否有意义。通常,如果类型的对象需要添加到某类集合时,或者这些对象主要用于存储一组字段或属性时, 我们需要实现值相等性的自定义处理。否则,我们定义的类或结构会使用默认的值相等性实现。此实现使用反射来检查类型中的所有字段和属性。尽管此默认的实现可以确保结果的正确性,但是与我们为类型编写的自定义实现相比,它的速度相对较慢。

为了实现自定义的值相等性,我们需要遵循下列的基础步骤来做:

  1. 重写Object.Equals(Object)方法。

  2. 通过提供类型特定的Equals方法实现System.IEquatable接口。实际的等效性比较将在此接口中执行。通常,我们可能决定通过仅比较类型中的一两个字段来定义相等性。

  3. 重载 == 和 != 符。

  4. 重写Object.GetHashCode方法,以便具有值相等性的两个对象生成相同的哈希代码。

  5. 若要支持“大于”或“小于”的定义,请为类型实现ICompare接口,并同时重载 <= 和 >= 运算符。

下面就以游戏中英雄数据类为例,来简要说明自定义的值相等性的实现。

当我们在定义英雄数据类时,一个英雄通常会包含各种各样的属性,比如英雄的ID,职业(战士、法师、弓箭手),等级,阵营等等。而我们在使用这些英雄的数据时,通常会把它们存储到某个集合之中,像是List、Dictionary之类,以便于我们的数据处理。那么在这时,我们就需要为英雄数据类实现一个自定义的值相等性处理,这样在访问集合中的英雄数据元素时,便可以调用我们自己编写的判断代码,而不用使用默认的使用反射的实现。

根据之前的描述,我们首先重写Object.Equals(Object)方法。

2.png

在Object.Equals(Object)方法的重写实现中,实际上调用了实现System.IEquatable接口的类型特定的Equals方法,来进行我们自定义的值相等性比较。在下面的示例代码中,我们仅通过一项英雄ID的比较,便完成了HeroModel类型的值相等性判断。这里做了一些简化,实际的比较条件会比这要略微复杂一些。但是通过我们的实现不难看出,在逻辑层面上定义出值相等性的判断条件,与它默认的实现相比,不论是在代码的执行效率上,还是代码所传达的含义上,都有不小的优势。

3.png

对于 == 和 != 操作符的重载,以及GetHashCode方法的重写,这里我们不在展开举例。希望大家在相等性判断这一基础操作的处理上,注意提取逻辑层面的比较因素,谨慎而为,确保比较的正确性。

 

战国工作室  供稿