从基础构造函数C#调用基类重写方法

时间:2017-08-18 09:09:11

标签: c# constructor polymorphism override

我希望有一个类,它将具有索引器和字段数,如下例所示:

public abstract class ARecord
{        
    public abstract double this[int index] { get; }
    public abstract int NumberOfFields { get; }
}

public class Record : ARecord
{
    public double Field1{ get; private set; }
    public double Field2{ get; private set; }

    public override int NumberOfFields { get { return 2; } }

    public Record(double[] records)
    {
        if (records.Count() != NumberOfFields) // PROBLEM IS HERE. WHEN CALLING THIS FROM DERIVED CLASS NumberOfFields=3!
            throw new ArgumentException();
        this.Field1= records[0];
        this.Field2 = records[1];
    }

    public override double this[int index]
    {
        get { throw new NotImplementedException(); }
    }     
}

public class ChildRecord : Record
{
    public double Field3 { get; private set; }

    public override int NumberOfFields { get { return 3; } }

    public ChildRecord(double[] records)
        : base(new double[] { records[0], records[1] })
    {
        if (records.Count() != NumberOfFields)
            throw new ArgumentException();
        this.Field3 = records[2];
    }

    public override double this[int index]
    {
        get { throw new NotImplementedException(); }
    }     
}

public static class TestRecord
{
    public static void CreateRecord()
    {
        var record = new ChildRecord(new double[]{1.0,1.5,2.5}); // Not working
    }
}

此示例因NumberOfFields构造函数内ChildRecord内的多态调用Record而崩溃。

据我所知,我可以new使用override来解决此问题,但在这种情况下,我无法在基类中将NumberOfFields声明为abstract (我需要的)。

解决此问题的正确方法是什么?设计有问题吗?

1 个答案:

答案 0 :(得分:0)

你已经制定了这个方法,它不可能按预期工作。假设它做了(通过某种神奇的方式)以你认为应该的方式工作,并且你能够创建你的ChildRecord

var record = new ChildRecord(new double[] { 1.0, 1.5, 2.5 });

您期望record.NumberOfFields的价值是多少?两三个?此特定对象不能是ChildRecord NumberOfFields == 3,同时Record NumberOfFields == 2。无论您将NumberOfFields键入为recordARecord还是Record,都会获得实例化类的ChildRecord实现结果。

换句话说:将ARecord.NumberOfFields暴露给外界是没有意义的,因为没有一个正确的答案 - 它不是一个有意义的概念。

如果您放弃暴露它,您可以进行类似这样的验证(省略索引器和属性):

public abstract class ARecord
{
    public abstract double this[int index] { get; }
}

public class Record : ARecord
{
    private const int NumberOfFields = 2;

    public Record(double[] records)
    {
        if (records.Count() != NumberOfFields)
            throw new ArgumentException();
        this.Field1 = records[0];
        this.Field2 = records[1];
    }
}

public class ChildRecord : Record
{
    private const int NumberOfFields = 3;

    public ChildRecord(double[] records)
        : base(new double[] { records[0], records[1] })
    {
        if (records.Count() != NumberOfFields)
            throw new ArgumentException();
        this.Field3 = records[2];
    }
}