NBMsgPack051: Prefer modern .NET APIs
Some APIs exist to support targeting .NET Standard or .NET Framework, while other APIs are available when targeting .NET that offer superior performance and reliability. This diagnostic is reported when code uses the lesser API while the preferred API is available.
The diagnostic message will direct you to the preferred API.
In multi-targeting projects where switching to the preferred API is inadvisable because it would break the build for older target frameworks or require the use of #if
sections, you may suppress this warning.
Example violation
The following code constructs a union type mapping. This method may fail at runtime if the type arguments are not attributed with GenerateShapeAttribute.
[GenerateShape]
partial class MyType { }
[GenerateShape]
partial class MyDerivedType : MyType { }
[GenerateShapeFor<MyType>]
partial class Witness;
class Foo
{
internal DerivedShapeMapping<MyType> ConstructUnionMapping()
{
DerivedShapeMapping<MyType> mapping = new();
mapping.AddSourceGenerated<MyDerivedType>(1);
return mapping;
}
}
This is acceptable for projects that target .NET Standard or .NET Framework because compile-time enforcement is not available. But if the project targets .NET a warning will be emitted to encourage use of the safer APIs.
Resolution
Per the message in the warning, switch to the overload that takes a type that is constrained to guaranteeing availability of its shape:
[GenerateShape]
partial class MyType { }
[GenerateShape]
partial class MyDerivedType : MyType { }
[GenerateShapeFor<MyType>]
partial class Witness;
class Foo
{
internal DerivedShapeMapping<MyType> ConstructUnionMapping()
{
DerivedShapeMapping<MyType> mapping = new();
mapping.Add<MyDerivedType>(1);
return mapping;
}
}
Or in a multitargeting project, use the preferred API only where it's available:
[GenerateShape]
partial class MyType { }
[GenerateShape]
partial class MyDerivedType : MyType { }
[GenerateShapeFor<MyType>]
partial class Witness;
class Foo
{
internal DerivedShapeMapping<MyType> ConstructUnionMapping()
{
DerivedShapeMapping<MyType> mapping = new();
#if NET
mapping.Add<MyDerivedType>(1);
#else
mapping.AddSourceGenerated<MyDerivedType>(1);
#endif
return mapping;
}
}
Tip
In a multi-targeting project, simply reducing the severity of the diagnostic from Warning to something lesser may be a better option than creating #if
/#else
/#endif
regions in many places.