C
C#12mo ago
SWEETPONY

❔ 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 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;
}
}
So implemented code allows use to do this:
var builder = new UISchemaBuilder()
.StartGroup("groupName")
.AddBoolean()
.EndGroup()
.StartGroup("anotherGroupName")
.AddBoolean()
.EndGroup()
.Build();
var builder = new UISchemaBuilder()
.StartGroup("groupName")
.AddBoolean()
.EndGroup()
.StartGroup("anotherGroupName")
.AddBoolean()
.EndGroup()
.Build();
22 Replies
SWEETPONY
SWEETPONY12mo ago
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?
ero
ero12mo ago
why do you need to change the type exactly?
SWEETPONY
SWEETPONY12mo ago
I can make some changes for netstandard:
+ public override UISchemaBuilderBase AddBoolean
- public override UISchemaGroupBuilder AddBoolean
+ public override UISchemaBuilderBase AddBoolean
- public override UISchemaGroupBuilder AddBoolean
but my builder will not work I can't use EndGroup after AddBoolean
public UISchemaBuilder EndGroup() =>
_schemaBuilder;
public UISchemaBuilder EndGroup() =>
_schemaBuilder;
ero
ero12mo ago
so, okay, explain this to me, how can you even override AddBoolean like that you're adding a parameter how is that possible?
MODiX
MODiX12mo ago
ero
REPL Result: Failure
class C
{
public virtual void M(string s1, string s2 = "") { }
}

class D : C
{
public override void M(string s1, string s2, string s3) => base.M(s1, s2, s3);
}
class C
{
public virtual void M(string s1, string s2 = "") { }
}

class D : C
{
public override void M(string s1, string s2, string s3) => base.M(s1, s2, s3);
}
Exception: CompilationErrorException
- 'D.M(string, string, string)': no suitable method found to override
- No overload for method 'M' takes 3 arguments
- 'D.M(string, string, string)': no suitable method found to override
- No overload for method 'M' takes 3 arguments
Compile: 473.613ms | Execution: 0.000ms | React with ❌ to remove this embed.
ero
ero12mo ago
?
SWEETPONY
SWEETPONY12mo ago
one moment
SWEETPONY
SWEETPONY12mo ago
GitHub
GitHub - INTERNALINTERFERENCE/CovariantTest
Contribute to INTERNALINTERFERENCE/CovariantTest development by creating an account on GitHub.
SWEETPONY
SWEETPONY12mo ago
simple repo
ero
ero12mo ago
it just seems like you're approaching this kinda incorrectly
SWEETPONY
SWEETPONY12mo ago
idk it works on net6 ahh I found how to fix this public new UISchemaGroupBuilder AddBoolean()
ero
ero12mo ago
an interface with TSelf might be better your abstract class doesn't even have any abstract members
SWEETPONY
SWEETPONY12mo ago
can you show an example?
ero
ero12mo ago
on it
SWEETPONY
SWEETPONY12mo ago
public abstract class UISchemaBuilderBase<TSchemaBuilder>
where TSchemaBuilder : UISchemaBuilderBase<TSchemaBuilder>
{
public virtual TSchemaBuilder AddBoolean() =>
throw new NotImplementedException();
}

public class UISchemaBuilder : UISchemaBuilderBase<UISchemaBuilder>
{
public override UISchemaBuilder AddBoolean() =>
throw new NotImplementedException();
}
public abstract class UISchemaBuilderBase<TSchemaBuilder>
where TSchemaBuilder : UISchemaBuilderBase<TSchemaBuilder>
{
public virtual TSchemaBuilder AddBoolean() =>
throw new NotImplementedException();
}

public class UISchemaBuilder : UISchemaBuilderBase<UISchemaBuilder>
{
public override UISchemaBuilder AddBoolean() =>
throw new NotImplementedException();
}
such that?
MODiX
MODiX12mo ago
ero
REPL Result: Success
Builder builder = new Builder()
.AddBoolean("", "")
.StartGroup()
.AddBoolean("", "")
.EndGroup();

interface IBuilder<out TSelf>
where TSelf : IBuilder<TSelf>
{
TSelf AddBoolean(string fieldName, string fieldTitle, string groupName = null);
}

class Builder : IBuilder<Builder>
{
public Builder AddBoolean(string fieldName, string fieldTitle, string groupName = null)
{
return this;
}

public GroupBuilder StartGroup()
{
return new(this);
}
}

class GroupBuilder : IBuilder<GroupBuilder>
{
private readonly Builder _parent;

public GroupBuilder(Builder parent)
{
_parent = parent;
}

public GroupBuilder AddBoolean(string fieldName, string fieldTitle, string groupName = null)
{
return this;
}

public Builder EndGroup()
{
return _parent;
}
}
Builder builder = new Builder()
.AddBoolean("", "")
.StartGroup()
.AddBoolean("", "")
.EndGroup();

interface IBuilder<out TSelf>
where TSelf : IBuilder<TSelf>
{
TSelf AddBoolean(string fieldName, string fieldTitle, string groupName = null);
}

class Builder : IBuilder<Builder>
{
public Builder AddBoolean(string fieldName, string fieldTitle, string groupName = null)
{
return this;
}

public GroupBuilder StartGroup()
{
return new(this);
}
}

class GroupBuilder : IBuilder<GroupBuilder>
{
private readonly Builder _parent;

public GroupBuilder(Builder parent)
{
_parent = parent;
}

public GroupBuilder AddBoolean(string fieldName, string fieldTitle, string groupName = null)
{
return this;
}

public Builder EndGroup()
{
return _parent;
}
}
Compile: 660.359ms | Execution: 45.369ms | React with ❌ to remove this embed.
SWEETPONY
SWEETPONY12mo ago
hm interesting! I like the interface usage @just_ero May I ask an immodest question? how long have you been programming in C#?
ero
ero12mo ago
i don't think i can answer that very clearly cause i don't do it professionally and i have never really completed a project
Vi Ness
Vi Ness12mo ago
That's a mood
ero
ero12mo ago
so i mean, i guess the first time i coded in c# was like 6 years ago or something (maybe more?) but it's not like i've just been grinding away at my programming skills every day i've never even read any books or watched tutorials
SWEETPONY
SWEETPONY12mo ago
incredible
Accord
Accord12mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.