views:

225

answers:

3

Hi guys Just wondering if there is any way to do the following:

public Interface IDataField 
{
    object GetValue();
}

public Interface IComplexDataField : IDataField
{
    object GetDefaultValue();
}

public class MyBase
{
    private IDataField _DataField;

    public MyBase()
    {
        this._DataField = this.CreateDataField();
    }

    public virtual IDataField CreateDataField()
    {
        return new DataField(); //Implements IDataField 
    }

    **public virtual IDataField GetDataField()**
    {
        return this._DataField;
    }

    public void SomeMethod()
    {
        this.GetDataField().GetValue();
    }
}


public class MyComplexBase : MyBase
{
    public override IDataField CreateDataField()
    {
        return new ComplexDataField(); //Implements IComplexDataField which Implements IDataField 
    }

    **public override IComplexDataField GetDataField()**
    {
        return (IComplexDataField)base.GetDataField();
    }

    public void SomeComplexSpecificMethod()
    {
        this.GetDataField().GetValue();
        this.GetDataField().GetDefaultValue();
    }
}

Cheers Anthony

+4  A: 

What you want is covariance of return types. This doesn't exist in C#.

Could you perhaps make MyBase generic:

public class MyBase<T> where T : IDataField
{
    public virtual T CreateDataField()
    {
        ... etc ...
    }
}

Alternatively, you can redeclare the method with "new" and shadow the base class method. Neither is particularly appealing...

Jon Skeet
A: 

The closest you can get in C# 3.0 is to have a separate virtual method (like your CreateDataField method) that does the actual work and can be overridden, then use new to re-declare the public method. i.e. in the base:

public IDataField GetDataField()
{
    return GetDataFieldImpl();
}
protected virtual IDataField GetDataFieldImpl()
{
    // return a basic version
}

and in the subclass:

protected override IDataField GetDataFieldImpl()
{
    // do something more fun
}
public new IComplexDataField GetDataField()
{
    return (IComplexDataField)GetDataFieldImpl();
}
Marc Gravell
A: 

What you're trying to do is called Covariant return types. They don't exist in the the current version C#, but there's talk of it being introduced for the next version.

Your best approach explained here: covariant return types

public class MyBase<T> where T : IDataField, new()
{
    public virtual T CreateDataField()
    {
        return new T();
    }

    public virtual T GetDataField()
    {
        return this._DataField;
    }

}

public class MyComplexBase : MyBase<ComplexDataField>
{
   ...
}