首页 > 解决方案 > 传递给函数(但不是本地)时列表元素的意外不平等

问题描述

我正在尝试实现一个比较不同列表元素的函数。我不断收到意想不到的行为,显然OpCodes.Brfalse != OpCodes.Brfalse12 != 12.

只有当我将项目列表作为参数传递给比较它们各个元素的函数时,它似乎才表现出这种行为,而不是当我在本地比较它们时。

[TestMethod()]
public void findListMatch_TEST()
{
    var alist = new List<Harmony.CodeInstruction>()
    {
        new Harmony.CodeInstruction(OpCodes.Brfalse, 12),
    };
    var blist = new List<Harmony.CodeInstruction>()
    {
        new Harmony.CodeInstruction(OpCodes.Brfalse, 12),
    };

    Assert.AreEqual(alist[0].opcode, blist[0].opcode); //Passes
    Assert.AreEqual(alist[0].operand, blist[0].operand); //Passes

    Assert.IsTrue(Foo(alist, blist)); //Fails
}

bool Foo(List<Harmony.CodeInstruction> alist, List<Harmony.CodeInstruction> blist)
{
    var A = alist[0];
    var B = blist[0];

    if (A.opcode != B.opcode)
    {
        return false; //Hit this sometimes, expect not to
    }
    else if (A.operand != B.operand)
    {
        return false; //Hit this sometimes, expect not to
    }
    return true;
}

Harmony.CodeInstruction是一个具有来自Harmony库的opcode{System.Reflection.Emit.OpCode} 和operand{object}字段的类。

标签: c#system.reflection

解决方案


CodeInstruction 类源代码中的操作数字段是对象类型。

Object.Equals因此,您的第一次比较使用方法检查是否相等

// Uses Object.Equals
Assert.AreEqual(alist[0].operand, blist[0].operand); 

您的第二个比较是参考等于,这将是错误的。

// Reference comparison will be false because both are boxing value 12 in different memory locations.
A.operand != B.operand

您可以在一个简单的控制台应用程序中轻松测试它

object a = 12;
object b = 12;
Console.WriteLine(a.Equals(b)); // True
Console.WriteLine(a == b); // False

推荐阅读