How to fix "Target runtime doesn't support covariant types in overrides?

I have Builder, let’s see code:

public abstract class UISchemaBuilderBase
{
   protected readonly UISchemaSpecification UiSchemaSpecification;

   public UISchemaSpecification Builder() =>
      UiSchemaSpecification;

   public virtual UISchemaBuilderBase AddBoolean(
       string fieldName,
       string groupName = null)

   {
       .. some logic
    
       UiSchemaSpecification.Properties[ fieldName ] = schema;
       return this;
   }
}
public class UISchemaBuilder : UISchemaBuilderBase
{
    public UISchemaBuilder() : base(new UISchemaSpecification()) { }

    public UISchemaGroupBuilder StartGroup(string name)
    {
        UiSchemaSpecification.ParsecMetadata ??= new();
        UiSchemaSpecification.ParsecMetadata.Groups ??= new();
        UiSchemaSpecification.ParsecMetadata.Groups.Add( new(name) );

        return new UISchemaGroupBuilder(name, this, UiSchemaSpecification);
    }
}
public class UISchemaGroupBuilder : UISchemaBuilderBase
{
    private readonly string _name;
    private readonly UISchemaBuilder _schemaBuilder;

    public UISchemaGroupBuilder(
       string name,
       UISchemaBuilder schemaBuilder,
       UISchemaSpecification specification)
       : base(specification)
    {
        _name = name;
        _schemaBuilder = schemaBuilder;
    }

   public override UISchemaGroupBuilder AddBoolean(
       string fieldName,
       string fieldTitle,
       string groupName = null)
    {
        base.AddBoolean(fieldName, fieldTitle, _name);
        return this;
    }

    public UISchemaBuilder EndGroup() =>
        _schemaBuilder;
}

So implemented code allows to do this:

var builder = new UISchemaBuilder()
  .StartGroup("groupName")
    .AddBoolean()
  .EndGroup()
  .StartGroup("anotherGroupName")
    .AddBoolean()
  .EndGroup()
  .Build();

The problem is: I can’t do the same in netstandard and I don’t understand how to fix this..
I should change return type of methods in UISchemaGroupBuilder. For example AddText should return UISchemaBuilderBase, not UISchemaGroupBuilder.
But if I follow by these advices, my builder wouldn’t work. I can’t use EndGroup after AddBoolean for example.
Can someone help me, please?

>Solution :

As per this article about C# versions from Microsoft:

.NET Standard 2.1 C# – 8.0

.NET Standard 2.0 C# – 7.3

But covariant return types is part of C# 9, thus it is not compatible with .Net Standard.

Basically covariant return types in override methods require changes in CLR in comparison with previous language version, so it is incompatible with in .Net Framework and .Net Standard.

In OP example, AddBool method of group builder could be a non-virtual method, just an overloaded one which hides method in the base class hierarchy:

public class UISchemaGroupBuilder : UISchemaBuilderBase
{
    ...
    public new UISchemaGroupBuilder AddBoolean(
       string fieldName,
       string fieldTitle,
       string groupName = null)
    {
        base.AddBoolean(fieldName, fieldTitle, _name);
        return this;
    }

Leave a Reply