Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override a generic base class property with a constructed return type

I want to use Generic type definitions in the Unity Editor and cannot (yet) update to Unity 2020.1 which natively supports this. The workaround is to define a non-generic class that extends the generic class. However, when I try to override a base class property, with a defined class which is basically a named version of the generic property, the compiler reports both types to be incompatible. Since this description is quite ... generic ... here is some code to illustrate my issue:

class Property<T> { }

class BaseClass<T>
{
    public virtual Property<T> Property { protected get; set; }
}

class StringProperty : Property<string> { }

class SubClass : BaseClass<string>
{
    public override StringProperty Property { protected get; set; }
}

SubClass.Property': type must be 'Property<string>' to match overridden member 'BaseClass<string>.Property

SubClass.Property is basically Property<string> but I don't know how to communicate this to the compiler.

like image 721
aleneum Avatar asked Oct 22 '25 07:10

aleneum


2 Answers

The issue is that while every StringProperty is a Property<string>, not every Property<string> is a StringProperty. Sounds weird? So here we go.

Imagine a client of your class has this:

BaseClass<string> b = new SubClass();

Now one would assume that we can do this:

b.Property = new MyProperty();

where MyProperty also derives from Property<string>. However this contradicts your expectation that instances of SubClass have a StringProperty, not a MyProperty.

That has nothing to do with generics. In short you cannot change the signature of a member by overriding it. Both the base-class- and the derived-class-member have to have the exact same signature, including the return-type.

like image 101
MakePeaceGreatAgain Avatar answered Oct 23 '25 22:10

MakePeaceGreatAgain


Covariant return types are not supported. I believe it is added with C# 9.

It means that you can not change the return type of the overridden method. Even if the overridden method returns a derived type.

Something like this is not valid:

class Animal
{

}

class Cat : Animal
{

}

abstract class AnimalFactory
{
    public abstract Animal CreateAnimal();
}

class CatFactory : AnimalFactory
{
    public override Cat CreateAnimal(); // Syntax error
}

Although we are returning an Animal (a Cat is an Animal), it will give a compiler error.

like image 42
ndogac Avatar answered Oct 23 '25 22:10

ndogac



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!