C# 如何强制派生类填充基类中定义的列表?
这是与C相关的,但实际上这个问题相当普遍 假设我有一个基类C# 如何强制派生类填充基类中定义的列表?,c#,polymorphism,C#,Polymorphism,这是与C相关的,但实际上这个问题相当普遍 假设我有一个基类 abstract class Base { protected List<string> MyList = new List<string>(); protected abstract void FillMyList(); } class Derived : Base { protected void FillMyList() { MyList.Add("test");
abstract class Base {
protected List<string> MyList = new List<string>();
protected abstract void FillMyList();
}
class Derived : Base {
protected void FillMyList() {
MyList.Add("test");
MyList.Add("test2");
}
}
这样就可以了,派生类将填充基类中定义的MyList
然而,除了抽象方法名FillMyList(这意味着您实际上必须填写MyList)之外,对于这个方法的含义没有任何线索
是否有更好的方法来强制执行或更好地强烈建议您在从Base继承时必须填写MyList?
可能将FillMyList声明为:
protected abstract void FillMyList(List<string> listToFill);
你有什么建议?如何定义填充?如果您只是想添加一些元素,那么您可以简单地添加另一个抽象方法来检索要添加的项,然后在基类中实现FillMyList以将这些项添加到列表中。例如:
abstract class Base
{
protected List<string> MyList = new List<string>();
protected abstract IEnumerable<string> GetItems();
protected void FillMyList()
{
MyList.AddRange(GetItems());
}
}
class Derived : Base
{
protected override IEnumerable<string> GetItems()
{
yield return "test";
yield return "test2";
}
}
完成此操作后,根据您的要求,可能适合将FillMyList更改为private。还要注意,派生中的方法必须标记为重写
当然,实现这一目标有很多不同的方法。例如,您可以按照Nagg的建议,简单地将MyList属性本身抽象化。如何定义填充?如果您只是想添加一些元素,那么您可以简单地添加另一个抽象方法来检索要添加的项,然后在基类中实现FillMyList以将这些项添加到列表中。例如:
abstract class Base
{
protected List<string> MyList = new List<string>();
protected abstract IEnumerable<string> GetItems();
protected void FillMyList()
{
MyList.AddRange(GetItems());
}
}
class Derived : Base
{
protected override IEnumerable<string> GetItems()
{
yield return "test";
yield return "test2";
}
}
完成此操作后,根据您的要求,可能适合将FillMyList更改为private。还要注意,派生中的方法必须标记为重写
当然,实现这一目标有很多不同的方法。例如,您可以简单地将MyList属性本身抽象化,正如Nagg所建议的那样。您可以使用getter将MyList转换为抽象属性,getter必须实现
public abstract class Base
{
public abstract List<int> List { get; }
}
public class Derived : Base
{
#region Overrides of Base
public override List<int> List
{
get { return new List<int> {1, 2, 3}; }
}
#endregion
}
可以使用getter将MyList转换为抽象属性,派生属性必须实现
public abstract class Base
{
public abstract List<int> List { get; }
}
public class Derived : Base
{
#region Overrides of Base
public override List<int> List
{
get { return new List<int> {1, 2, 3}; }
}
#endregion
}
我认为,如果有什么地方不对劲,例如,列表没有正确填写,那么当你试图使用它时,你应该抛出一个异常。这样,您将始终获得正确的数据。即使类是抽象的,用户也可以将其实现为空方法,因此这不是更好的方法。我认为,如果出现问题,即列表填写不正确,则在尝试使用它时应该抛出异常。这样,您将始终获得正确的数据。即使类是抽象的,用户也可以将其实现为空方法,因此这并不是更好的方法。您可以这样做:
abstract class Base {
protected List<string> TheList
{
get {
Debug.Assert(MyList.Count != 0);
return MyList;
}
set {
Debug.Assert(value.Count != 0);
MyList = value;
}
}
private List<string> MyList = new List<string>();
}
您的派生对象只能通过执行检查的属性访问MyList。您可以执行以下操作:
abstract class Base {
protected List<string> TheList
{
get {
Debug.Assert(MyList.Count != 0);
return MyList;
}
set {
Debug.Assert(value.Count != 0);
MyList = value;
}
}
private List<string> MyList = new List<string>();
}
您的派生对象只能通过将执行检查的属性访问MyList。抽象方法和属性都具有相同的效果,即必须在Nagg中实现它,这就实现了。谢谢@saurabh:是的,但这会迫使派生函数执行某些操作,并实际返回列表,即使列表为空。抽象方法和属性都会产生相同的效果,即必须在Nagg中实现它,这就完成了。谢谢@saurabh:是的,但这会迫使派生函数做一些事情,并实际返回列表,即使列表为空。谢谢Will,你的答案也很有趣:谢谢Will,你的答案也很有趣: