繁体   English   中英

将动态 object 传递给 .NET 6 中的自定义插值字符串处理程序时出现无效的实例化异常

[英]Invalid instantiation exception when pass dynamic object to custom interpolated string handler in .NET 6

我在我的记录器方法中发现了升级到 .NET 6 LogErrorInterpolatedStringHandler的问题。

这是经典的方法:

public static void Log(string message, params object[] pars)
{
    // Log message
}

这是升级后的:

public static void Log(ref LogErrorInterpolatedStringHandler message, params object[] pars)
{
    // Log message
}

我升级了该方法以获得此处描述的 C# 10 和 .NET 6 的性能改进。

该方法的新版本运行良好,除了在插值字符串中传递dynamic object 时。

这是一个例子:

// Works well   
Logger.Log($"Log: {stringOrEverythingElseObject}");

// Exception
Logger.Log($"Log: {dynamicObject}");

抛出的异常是

通用类型“<>A{00000004}`3”在程序集“MyAssembly,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”中与无效实例化一起使用。

我发现了一个类似于我的问题的拉取请求,但无法理解如何在我的代码中修复。

你有什么主意吗? 谢谢

TL;博士

除了在呼叫站点将dynamicObject转换为object之外,您无能为力:

Logger.Log($"Log: {(object)dynamicObject}");

或从处理程序中删除ref

[InterpolatedStringHandler]
public struct LogErrorInterpolatedStringHandler

但不确定它将如何影响性能(尽管使用dynamic应该比这对性能有更大的影响,通常你应该避免在性能敏感代码中使用dynamic

试图解释

由于以下限制ref struct不能很好地与dynamic一起使用:

  • ref结构不能是类型参数。

而处理dynamic的代码使用相关类型作为类型参数。 即以下代码:

var handler = new Handler();
handler.AppendFormatted((dynamic)5);

ref struct Handler
{
    // or public void AppendFormatted<T>(T value) { }
    public void AppendFormatted(object value) { }
}

将导致编译器生成类似这样的内容:

private static class <>o__0
{
    public static CallSite<<>A{00000002}<CallSite, Handler, object>> <>p__0;
}

请注意类型参数列表中的Handler ,这将导致完全相同的运行时错误。 从处理程序中删除ref可以解决此问题。

正如本测试中的评论和Stephen Toub的评论中所指出的,目前 Roslyn 在运行时失败时不会为此代码发出任何构建时错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM