【问题标题】:C# calling un-implemented method in abstract interface implementationC# 在抽象接口实现中调用未实现的方法
【发布时间】:2013-10-04 13:11:31
【问题描述】:

有一个接口OptionsSet和一个抽象类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;
        }
    }

}

为什么我不能从StringBasedOptionSet.getInt(string) 调用getString(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

我还尝试调用 OptionsSet.getString(key)base.getString(key),这会导致 非静态方法 / 对象不包含 getString 的定义 错误。

编辑StringBasedOptionsSet 没有实现OptionsSet 接口是在剥离示例时出现的错误。它确实在我的实际代码中实现了接口。

【问题讨论】:

    标签: c# interface abstract-class


    【解决方案1】:

    因为 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;
            }
        }
    
    }
    

    您可能还需要在抽象类中再次定义该函数。

    【讨论】:

    • Uups,我的示例代码缺少实现。当我实际尝试时,它确实实现了接口。
    • 抽象类没有实现接口这一事实并不是编译器错误的原因。正在执行此操作的类中缺少 getString 方法。实现接口只会创建下一个编译器错误,该类没有正确实现它。该类实际上根本不需要实现接口,可以在派生类上完成,基类方法将满足接口,但这在很大程度上是无意义的。
    • @NiklasR 请提供正确的代码。根据提供的代码,您得到的编译器错误是因为您试图调用一个不存在的方法。
    【解决方案2】:

    您需要在抽象类定义中将方法作为abstract 存根或适当的方法(可选virtual)提供:

    public abstract string getString(string key);
    

    或者:

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

    这是template method pattern

    如果您打算强制派生类型提供getString,则需要abstract 方法。如果您不想强制它,但允许它被覆盖,则需要默认的 virtual 方法。

    请注意,你的抽象类不需要直接实现接口,这可以在派生类中完成,只要方法定义正确,接口仍然可以满足:

    interface IFoo
    {
        string GetFoo();
    }
    
    abstract class FooBase
    {
        public virtual string GetFoo()
        {
            return "Adam";
        }
    }
    
    class Foo : FooBase, IFoo
    {
    }
    

    但是,你可能无论如何都不想这样做,这种设计似乎有点荒谬。

    此外,C# 命名约定支持方法名称的标题大小写,因此 GetIntGetString。接口的命名约定是以I为前缀:IOptionSet

    【讨论】:

      【解决方案3】:

      嗯,您的抽象类应该实现接口(因为它似乎是它的具体基础实现)并按照 Adam 的建议将 getString() 实现为抽象方法。

      结果是

      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;
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-04
        • 1970-01-01
        • 2018-01-21
        • 2018-07-13
        • 2011-05-01
        • 2011-11-20
        • 1970-01-01
        相关资源
        最近更新 更多