【问题标题】:C# emit , type value compareC# 发射,类型值比较
【发布时间】:2019-02-14 18:58:40
【问题描述】:

我的预览问题how to write a if statement

setterBuilder 语句中,如果我比较新值和旧值,有 3 种方式。

  1. 如@DudiKeleti 所写,使用“op_Inequality”。
  2. 使用property.PropertyType.GetMethod("Equals",有时会报错,"System.NullReferenceException"
  3. 使用 typeof(object).GetMethod("Equals" .

我的问题是什么。

  1. 某些数据类型,例如 int,没有“op_Inequality”,那我该怎么办?

  2. 如果我使用typeof(object).GetMethod,我也应该使用调试模型,否则会出现错误, System.AccessViolationException: '试图读取或写入受保护的内存。这通常表明其他内存已损坏。'

有人可以帮我解决问题吗?

更新 1

我有一个屏幕快照。

【问题讨论】:

  • 真的很难说任何有用的东西,因为你的问题问了很多东西,但没有很多细节。从您的屏幕截图中,您似乎正在尝试在 int 上调用 object.Equals。显然这行不通,您必须致电int.Equals(int)(另一种方法)。如果你想比较整数,use ceq.
  • 如果你想比较任意两个值,不管它们的类型如何,那么在 C# 中你会写EqualityComparer<T>.Default.Equals(a, b),它编译to this IL。也许这就是你所追求的?从你的问题很难说。
  • @canton7 感谢您的回答。我已经解决了。我会发布答案。
  • 对这个问题的一般、全面的回答是“充当编译器”。编译器有很多东西的特殊情况。由于有用于比较基本值(例如整数)的单独指令,因此不必进行调用,可以发出简单的“将值加载到堆栈并在 X 上分支”。问题是您需要了解所有这些事情。编写通用代码生成是困难

标签: c# emit


【解决方案1】:

谢谢大家。我得到了对EntityProxyFactory 的引用。这很有帮助 我的代码如下。

        Label exitSet = setIl.DefineLabel();
        MethodInfo op_inequality = propertyType.GetMethod("op_Inequality", new Type[] { propertyType, propertyType });
        if (op_inequality != null)
        {
            setIl.Emit(OpCodes.Ldarg_0);
            setIl.Emit(OpCodes.Ldfld, fb);
            setIl.Emit(OpCodes.Ldarg_1);
            setIl.Emit(OpCodes.Call, op_inequality);
            setIl.Emit(OpCodes.Brfalse_S, exitSet);
        }
        else
        {
            // Use object inequality
            setIl.Emit(OpCodes.Ldarg_0);
            setIl.Emit(OpCodes.Ldfld, fb);
            if (propertyType.IsValueType)
            {
                setIl.Emit(OpCodes.Box, propertyType);
            }
            setIl.Emit(OpCodes.Ldarg_1);
            if (propertyType.IsValueType)
            {
                setIl.Emit(OpCodes.Box, propertyType);
            }
            setIl.Emit(OpCodes.Call, EqualsMethod);
            setIl.Emit(OpCodes.Brtrue_S, exitSet);
        }


        setIl.Emit(OpCodes.Ldarg_0); // load string literal
        setIl.Emit(OpCodes.Ldarg_1); // value
        //-----------------important---------
        if (propertyType.IsValueType)
        {
            setIl.Emit(OpCodes.Box, propertyType);
        }
        setIl.Emit(OpCodes.Ldstr, property.Name);

        var parentType = tb.BaseType;
        //if (parentType == null)
        //    throw new Exception($"Interface {tb.Name} should be inherited from \"IDbEntity\". ");

        var m = parentType.GetMethod("ValueChanged", BindingFlags.Instance | BindingFlags.NonPublic);
        setIl.Emit(OpCodes.Call, m);

希望我的代码对你有所帮助。

【讨论】:

    猜你喜欢
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 2019-09-28
    • 2010-10-17
    相关资源
    最近更新 更多