【问题标题】:Inherit from an abstract base with a more specific method使用更具体的方法从抽象基础继承
【发布时间】:2013-03-01 17:37:16
【问题描述】:

这些关键词有很多问题;我筛选了前 30 个左右,然后放弃了。

我有这样的接口:

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

...这个想法是,可以实现IColumnRule&lt;T&gt; 来创建一个使用Func&lt;string, T&gt; 的强类型列解析器。

问题是,我将这些IColumnRule&lt;T&gt; 混凝土存储在IList&lt;IColumnRule&gt; 容器中。 IColumnRule&lt;T&gt; 有多种类型,每种都在不同的类型上实现。当我在IColumnRule 接口上调用Parse 方法时,我期望调用子类的new Parse(string) 方法,但实际上调用的是基类Parse

如何使用接口的object Parse(string)IColumnRule 的集合中调用子类泛型T Parse(string) 方法...或者这是不可能的?

【问题讨论】:

  • 这是您在声明 new 函数时得到的明确行为。见here
  • 几分钟前您的问题中有您的实施细节,但删除了它们。这有助于解释您遇到问题的原因。我已经用更详细的解决方案更新了我的答案,应该会对您有所帮助。
  • @p.s.w.g 是的,我认为这是太多的信息,并且会成为 TL;DR 有点像。你的答案就是我想要的;谢谢。

标签: c# generics inheritance overriding


【解决方案1】:

IColumnRule&lt;T&gt; 的实现必须提供兼容的Parse 方法。给定您的代码,最简单的方法是在您的基类中使用受保护的抽象方法,该方法在您的子类中被覆盖。

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

【讨论】:

  • @JeremyHolovacs 你可以创建IColumnRule的集合就好了,轻松搞定rulesCollection.Select(r =&gt; r.Parse(rowdata))
  • 这基本上就是我最终要做的。谢谢!
【解决方案2】:

当我在 IColumnRule 接口上调用 Parse 方法时,我希望调用子类的新 Parse(string) 方法,但实际调用的是基 Parse。

是的,会的。就类型系统、CLR 和编译器而言,您有两种方法不相关

如何使用接口的对象 Parse(string) 从 IColumnRule 集合中调用子类通用 T Parse(string) 方法...或者这是不可能的?

最简单的方法是有一个抽象类来实现它:

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

    ...
}

(如果两个方法名不同,会稍微简单一些。)

【讨论】:

    【解决方案3】:

    你必须以某种方式知道类型:

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

    或者只是转换一个已知元素:

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

    【讨论】:

      猜你喜欢
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 2013-10-21
      • 2014-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多