我想要一个类,它将有一个索引器和字段数,如以下示例所示:
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 == 3
的ChildRecord
,同时又是具有NumberOfFields == 2
的Record
。您将获得实例化类的NumberOfFields
实现的结果,无论您键入record
为ARecord
、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];
}
}