A commonly requested feature in .NET is the ability to use covariant return types. An example of this would be overriding “virtual object Clone()” with “override Widget Clone()”. From a type safety perspective, this is perfectly acceptable, but C# doesn’t currently allow it.
Under the covariant return types proposal, this rule would be relaxed and your subclasses methods could offer more specific return types than the base class version of the same method. Beside Clone, this could be useful when working abstract factories and other framework code.
Implicit Shadowing
One possible implementation is for C# to emit two functions. Using Clone as an example, you would see these signatures in IL:
override object Clonable.Clone()
public new Widget Clone()
According to HaloFour, this can work because:
It seems that the Common Language Runtime spec does permit an override to have a different name and potentially different visibility.
[…]
Through explicit use of the .override clause in IL I was able to resolve all of the overload resolution issues. I was able to override using a method with a different visibility and name.
This compiler-only feature would work seamlessly with existing versions of the CLR and older versions of VB or C# would be able to consume such classes without a problem.
But there are some limitations. Attributes that are normally inherited by overriding methods wouldn’t be copied into the new method. Technically, the compiler could copy the base class attributes onto the new method, but this also has problems as it would require a recompile of the subclass whenever new attributes are added to the base class method.
It would also be harder to see the relationship between the new method, and the base class method is overrided when using reflection.
Finally, there may be performance ramifications for calling the method through its base class interface. However, it may be possible to mitigate it using tail calls and other optimization techniques.
Attributes
Another possible implementation would use a new attribute. Compilers that recognize the attribute could then automatically add the cast to the more specific type.
The downside of this is that languages that don’t understand the new attribute couldn’t take advantage of this feature. And of course, that new attribute would have to be added to the BLC (Base Class Library), meaning it wouldn’t be immediately available on all platforms.
Another downside is that it may introduce an unnecessary boxing operation when dealing with structs. To continue our Clone example, the compiler would have to box a WidgetStruct, then immediately cast it back to a normal WidgetStruct.
Relaxed Shadowing/Overriding
An alternative to this feature would be relaxing the rules on shadowing. Currently you cannot both shadow and override the same method. But since the CLR supports it, C# could simply allow you to explicitly write code such as:
class Widget : Cloneable
{
public override Cloneable Clone()
{
return this.Clone();
}
public new Widget Clone()
{
return [...];
}
}
As with implicit shadowing proposal, this would rely on the compiler to rename the overriding method.
Timelines
It should be noted that most of the discussions about this feature happened in early 2015, over two years ago. And nothing has been done with it, at least publicly, since the proposal was formally written up back in February.