【问题标题】:Why does calling a generic local function with a dynamic parameter produce a BadImageFormatException?为什么使用动态参数调用通用本地函数会产生 BadImageFormatException?
【发布时间】:2018-01-11 17:55:40
【问题描述】:

玩弄 C# 7 的本地函数后,我发现了一些有趣的行为。考虑以下程序:

public void Main()
{
    Console.WriteLine("Entered Main");
    DoSomething("");
}

private void DoSomething(object obj)
{
    Console.WriteLine("Entered DoSomething");
    Generic((dynamic)obj);
    GenericLocal(obj);
    GenericLocal((dynamic)obj); // This breaks the program

    void GenericLocal<T>(T val) => Console.WriteLine("GenericLocal");
}

private void Generic<T>(T val) => Console.WriteLine("Generic");

这会产生:

进入主界面

...然后抛出BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)。堆栈跟踪:

   at UserQuery.DoSomething(Object obj)
   at UserQuery.Main()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

(我在 LINQPad 中运行它,但我从 dotnetfiddle 得到了类似的结果。)

删除代码中指示的行会产生您期望的输出:

进入主界面
进入 DoSomething
通用
通用本地

谁能解释一下原因?

【问题讨论】:

  • 对我来说,这看起来像是 .NET/C# 工具链中的某个错误。
  • 我想你已经知道你发现了一个错误。
  • Mono 也有同样的错误,同样的异常消息是“Method with open type while not compiling gshared”
  • 也发生在交互式编译器 (csi.exe) 上。你应该打开一个问题here
  • Done。感谢您的反馈。

标签: c# generics dynamic c#-7.0


【解决方案1】:

这个turned out to be a bug,但是当 dotnet 团队对其进行调查时,他们意识到他们无法轻易解决问题,因此本地泛型方法的工作方式与非本地泛型方法的工作方式相同。所以改为they opted 让编译器在您尝试执行此操作时产生错误。

CS8322 无法将具有动态类型的参数传递给具有推断类型参数的通用本地函数“GenericLocal”。

【讨论】:

    【解决方案2】:

    只要你稍微帮助编译器,代码就不会中断:

    GenericLocal<dynamic>((dynamic)obj); // This doesn't break the program
    

    【讨论】:

    • 确实如此。但是,它与(dynamic) 演员的目的背道而驰。当我调用Generic((dynamic)obj) 时,泛型类型Tstring(因为这是运行时对象的基础)。调用GenericLocal&lt;dynamic&gt;((dynamic)obj) 将泛型类型粘贴为object,这与调用GenericLocal(obj) 没有什么不同。
    • 当泛型参数受到限制时,这不是解决方案。如果 GenericLocal 被定义为 void GenericLocal&lt;T&gt;(T arg) where T : Exception 这将无法编译。
    猜你喜欢
    • 2016-02-03
    • 2017-01-26
    • 1970-01-01
    • 2018-12-31
    • 1970-01-01
    • 2018-03-06
    • 2015-04-11
    • 2016-09-19
    • 1970-01-01
    相关资源
    最近更新 更多