You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

动态生成方法(如IL发射)中能否触发隐式转换运算符?

问题描述

定义如下C#类:

public class A 
{
}
    
public class B  
{
    public static implicit operator A(B value)
    {
        return new A();
    } 
}

编译时,以下两种转换代码均可正常执行:

// 隐式转换写法
A a = new B();
// 显式转换写法
B b = new B();
A a = (A)b;

但通过DynamicMethod动态生成IL代码执行转换时,抛出InvalidCastException:

DynamicMethod method = new DynamicMethod("", typeof(A), new [] { typeof(B) });
ILGenerator gen = method.GetILGenerator();

gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Castclass, typeof(A)); // 使用了强制类型转换的IL指令
gen.Emit(OpCodes.Ret);    
Func<B, A> fn = (Func<B, A>)method.CreateDelegate(typeof(Func<B, A>));

A instance = fn(new B());

报错信息:

InvalidCastException: Unable to cast object of type 'B' to type 'A'.

疑问

隐式转换是否仅为编译时语法糖,运行时常规转换无法识别?求确认及解决方法,因使用的第三方IL生成库未自动处理该转换。


回答

确认:自定义隐式/显式转换属于编译时语法糖

C#中的自定义隐式、显式转换运算符,本质就是编译期的语法糖。编译器遇到A a = new B()或者(A)b这类写法时,会自动将代码替换为对public static implicit operator A(B value)这个静态方法的调用,而非生成类型强制转换的IL指令。

你在动态IL中使用的OpCodes.Castclass是运行时原生类型强制转换指令,它只会检查对象实际类型与目标类型的继承/接口实现关系,完全不会识别自定义转换运算符——二者属于完全不同的机制。

解决方法:在IL中直接调用自定义转换运算符的静态方法

要实现正确转换,需要在IL里生成调用B类的implicit operator A(B)静态方法的指令,替换掉Castclass指令。修改后的代码如下:

DynamicMethod method = new DynamicMethod("", typeof(A), new [] { typeof(B) });
ILGenerator gen = method.GetILGenerator();

gen.Emit(OpCodes.Ldarg_0);
// 调用B类的隐式转换静态方法,替代Castclass指令
gen.Emit(OpCodes.Call, typeof(B).GetMethod("op_Implicit", new[] { typeof(B) }));
gen.Emit(OpCodes.Ret);    

Func<B, A> fn = (Func<B, A>)method.CreateDelegate(typeof(Func<B, A>));
A instance = fn(new B());

补充说明

  • 如果是自定义显式转换运算符(public static explicit operator A(B value)),对应的静态方法名为op_Explicit,调用时替换为该方法名即可。
  • 若不确定转换类型,可通过反射遍历目标类型的静态方法,筛选出返回类型为目标类型、参数为源类型的op_Implicit或op_Explicit方法。

内容的提问来源于stack exchange,提问作者tigrou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 13:43:27