Cook Computing

Covariant Return Types

May 30, 2002 Written by Charles Cook

Last night I was experimenting with some code to parse XML documents using XmlReader. I was representing each element type by a separate class deriving from a class called ParserBase. The base class does the basic work of moving the reader from node to node, calling the relevant virtual methods to get the derived classes to do some work. Once the element has been processed the ParserBase.Parse method returns an object containing the result of parsing the element:


class BaseParser
{
  ...
  public virtual Object Parse() { return new Object() };
}

and I would like a derived class to look like this, overriding Parse:


class FaultParser
{
  ...
  public override Fault Parse() { return new Fault() };
}

You should have guessed by now that I'm going to complain that C# doesn't support covariant return types. Code like this won't compile. Covariant in this context means that something - the return type - varies in the same direction as something else - the class type. As the class type becomes more specialized, FaultParser derives from ParserBase, the return type become more specialized, Fault derives from Object.

Covariant return types are uncontentious. Unlike other forms of covariance which I'll discuss in another post, I've not seen any argument against covariant return types. The compiler can check that their usage is statically correct and so they incur no runtime cost. Unfortunately they are not supported by the CLR.