I found an issue upgrading to the .NET 6 LogErrorInterpolatedStringHandler
in my logger method.
Here is the classic method:
public static void Log(string message, params object[] pars)
{
// Log message
}
and here is the upgraded one:
public static void Log(ref LogErrorInterpolatedStringHandler message, params object[] pars)
{
// Log message
}
I upgraded the method in order to get the performance improvements of C# 10 and .NET 6 described here.
The new version of the method works well except when passing dynamic
object in the interpolated string.
Here is an example:
// Works well
Logger.Log($"Log: {stringOrEverythingElseObject}");
// Exception
Logger.Log($"Log: {dynamicObject}");
The exception thrown is
The generic type '<>A{00000004}`3' was used with an invalid instantiation in assembly 'MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
I found a pull request similar to my problem but could not understand how to fix in my code.
Do you have any idea? Thanks!
TL;DR
There is not much you can do except casting dynamicObject
to object
at the call site:
Logger.Log($"Log: {(object)dynamicObject}");
or removing ref
from the handler:
[InterpolatedStringHandler]
public struct LogErrorInterpolatedStringHandler
But not sure how it will affect performance (though using dynamic
should have much more effect on performance than this, in general you should avoid dynamic
in performance sensitive code)
Attempt to explain
ref struct
s do not work with dynamic
very well due to the following limitation:
- A
ref
struct can't be a type argument.
While code handling the dynamic
uses the related types as type parameters. I.e. the following code:
var handler = new Handler();
handler.AppendFormatted((dynamic)5);
ref struct Handler
{
// or public void AppendFormatted<T>(T value) { }
public void AppendFormatted(object value) { }
}
Will result in something like this generated by compiler:
private static class <>o__0
{
public static CallSite<<>A{00000002}<CallSite, Handler, object>> <>p__0;
}
Note the Handler
in the list of type parameters which will lead to the exactly the same runtime error. Removing ref
from the handler fixes the issue.
As noted in comments in this test and this comment by Stephen Toub currently Roslyn does not emit any build time errors for this code while it fails in runtime.