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



我想要一个类,它将有一个索引器和字段数,如以下示例所示:

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

此示例崩溃,因为来自Record构造函数内部ChildRecord多态调用NumberOfFields

据我所知,我可以使用new而不是override来解决这个问题,但在这种情况下,我不能在基类(我需要(中将NumberOfFields声明为abstract

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

你制定的方式,它不可能按预期工作。假设它确实(通过某种魔法(按照您认为应该的方式工作,并且您能够创建您的ChildRecord

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

您期望record.NumberOfFields的价值是什么?两三个?这个特定的对象不能是具有NumberOfFields == 3ChildRecord,同时又是具有NumberOfFields == 2Record。您将获得实例化类的NumberOfFields实现的结果,无论您键入recordARecordRecord还是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];
}
}

最新更新