Niklas R
Niklas R

Reputation: 16890

C# calling un-implemented method in abstract interface implementation

There's an interface OptionsSet and an abstract class StringBasedOptionsSet.

interface OptionsSet {

    string getString(string key);

    int getInt(string key);

}

abstract class StringBasedOptionsSet : OptionsSet {

    int getInt(string key) {
        string v = getString(key);
        try {
            return Convert.ToInt32(v);
        }
        catch (Exception exc) {
            if (exc is FormatException || exc is OverflowException) {
                return 0;
            }
            throw;
        }
    }

}

Why can't I call the getString(string) method from StringBasedOptionSet.getInt(string)?

csmade/StringBasedOptionsSet.cs(21,36): error CS0103: The name `getString' does not exist in the current context
csmade/StringBasedOptionsSet.cs(32,25): error CS0103: The name `getString' does not exist in the current context

I also tried invoking OptionsSet.getString(key) and base.getString(key) which leads to non-static method / object does not contain definition for getString errors.

Edit: That StringBasedOptionsSet does not implemented the OptionsSet interface was a mistake while stripping down the example. It does implemented the interface in my actual code.

Upvotes: 1

Views: 401

Answers (3)

Adam Houldsworth
Adam Houldsworth

Reputation: 64517

You need to provide the method as an abstract stub or proper method (optionally virtual) inside your abstract class definition:

public abstract string getString(string key);

Or:

public virtual string getString(string key)
{
    return null;
}

This is the template method pattern.

If you intend to force derived types to provide getString then an abstract method is required. If you do not want to force it, but allow it to be overridden then a default virtual method is required.

Note that your abstract class does not need to implement the interface directly, this can be done at the derived class and the interface will still be satisfied so long as the methods are defined correctly:

interface IFoo
{
    string GetFoo();
}

abstract class FooBase
{
    public virtual string GetFoo()
    {
        return "Adam";
    }
}

class Foo : FooBase, IFoo
{
}

However, you probably wouldn't want to do this anyway, this type of design seems a little nonsensical.

Also, C# naming convention favours title case for method names, so GetInt and GetString. Naming convention for interfaces is to prefix with I: IOptionSet.

Upvotes: 1

user2846770
user2846770

Reputation:

Hmm, your abstract class should implement the interface (since it seems to be a concrete base implementation of it) and implement getString() as abstract methode as Adam suggested.

The result would be

abstract class StringBasedOptionsSet : OptionsSet
{
    public abstract string getString(string key);

    public int getInt(string key) 
    {
        string v = getString(key);
        try {
            return Convert.ToInt32(v);
        }
        catch (Exception exc) {
            if (exc is FormatException || exc is OverflowException) {
                return 0;
            }
            throw;
        }
    }
}

Upvotes: 0

Dean Fenster
Dean Fenster

Reputation: 2395

Because StringBasedOptionsSet doesn't implement the interface, your class should be:

interface OptionsSet {

    string getString(string key);

    int getInt(string key);

}

abstract class StringBasedOptionsSet : OptionsSet {

    int getInt(string key) {
        string v = getString(key);
        try {
            return Convert.ToInt32(v);
        }
        catch (Exception exc) {
            if (exc is FormatException || exc is OverflowException) {
                return 0;
            }
            throw;
        }
    }

}

You might also need to define the function again in the abstract class.

Upvotes: 1

Related Questions