user610217
user610217

Reputation:

Inherit from an abstract base with a more specific method

Lots of questions with these keywords; I sifted through the first 30 or so then gave up.

I have interfaces like so:

public interface IColumnRule
{
    int Length { get; set; }
    string Name { get; set; }
    object Parse(string toParse);
    int Position { get; set; }
    Type Type { get; }
}

public interface IColumnRule<T> : IColumnRule
{
    ColumnRule<T>.RuleFluentInterface<T> Configure { get; }
    new T Parse(string rowdata);
    Func<string, T> ParsingFunction { get; set; }
}

... the idea being, one would implement the IColumnRule<T> to create a strongly-typed column parser utilizing the Func<string, T>.

The problem is, I store these IColumnRule<T> concretes in an IList<IColumnRule> container. There are multiple types of IColumnRule<T>, each implementing on a different type. When I invoke the Parse method on the IColumnRule interface, I am expecting the new Parse(string) method of the subclass to be called, but the base Parse is the one actually being called.

How can I invoke the subclass generic T Parse(string) method from a collection of IColumnRule using the interface's object Parse(string) ... or is this impossible?

Upvotes: 0

Views: 85

Answers (3)

p.s.w.g
p.s.w.g

Reputation: 149088

Your implementation of IColumnRule<T> would have to provide a compliant Parse method. Given your code, the easiest way to do that is with an protected abstract method in your base class which is overridden in your subclass.

public abstract class ColumnRule : IColumnRule
{
    ...

    public object Parse(string rowdata)
    {
        return this.ParseInternal(rowdata);
    }

    protected abstract object ParseInternal(rowdata);
}

public class ColumnRule<T> : ColumnRule, IColumnRule<T>
{
    ...

    public new T Parse(string rowdata)
    {
        // strong-typed parse method
    }

    protected override object ParseInternal(string rowdata)
    {
        return this.Parse(rowdata); // invokes strong-typed method
    }
}

Upvotes: 3

itsme86
itsme86

Reputation: 19526

You'd have to know the type somehow:

List<IColumnRule> rules;  // populated from somewhere

foreach (IColumRule<int> rule in rules.OfType<IColumnRule<int>>()) {
    int foo = rule.Parse(rowData);
}

Or just cast a known element:

int foo = ((IColumnRule<int>)rules[5]).Parse(rowData);

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503974

When I invoke the Parse method on the IColumnRule interface, I am expecting the new Parse(string) method of the subclass to be called, but the base Parse is the one actually being called.

Yes, it would. You've got two methods which are unrelated as far as the type system, CLR and compiler are concerned.

How can I invoke the subclass generic T Parse(string) method from a collection of IColumnRule using the interface's object Parse(string) ... or is this impossible?

The simplest approach would be to have an abstract class implementing this as:

public abstract ColumnRuleBase<T> : IColumnRule<T>
{
    public object Parse(string toParse)
    {
        IColumnRule<T> genericThis = this;
        return genericThis.Parse(toParse);
    }

    ...
}

(If you had the two method names being different, it would be slightly simpler.)

Upvotes: 1

Related Questions