来自数据科学领域,我正尝试学习使用c#进行软件开发的方法。
我正在尝试建立一个基础类(例如Aliments),从中可以衍生出其他一些甚至更具体的自定义列表类(例如Fruits和Vegs)。在侧面,我有一些分别来自Aliment的Fruit和Veg类。最后,我希望Fruits / Vegs实例具有Veg / Fruit专有性列表(以及一些针对Fruits和Vegs类的专有性和方法)。但我希望此清单专有性可以在Aliments基类中实现,并提供一些管理它的方法(例如RemoveRipe(),SortBySize()...)
我试图在Aliments类中放置一个List适当性,然后使用List
我尝试过这样的事情:
public abstract class Aliment
{
public int Ripeness;
}
public class Fruit : Aliment
{
// be a fruit
}
public abstract class Aliments
{
public Aliments(List<Aliment> alimentList)
{
AlimentList = alimentList;
}
public List<Aliment> AlimentList { get; private set; }
public void RemoveRipe()
{
//...
}
}
public class Fruits : Aliments
{
public Fruits(List<Fruit> fruitList)
: base(fruitList)
{
}
}
主要问题是水果清单无法转换为食品清单。此外,操作的重点是每个“水果”实例都有一个“实际水果”列表(以便我可以访问“水果”的特定方法)。有什么办法可以做到吗?我的方法好吗? 预先感谢
P.S。抱歉,如果重复的话,我真的没怎么提出问题以进行搜索
答案 0 :(得分:2)
当我们说不能将List<Fruit>
转换为List<Aliment>
时,很大程度上取决于我们所说的“转换”。
如果您有一个List<Fruit>
并且想要一个List<Ailment>
,则可以通过创建一个新列表来实现。例如,如果fruitList
是List<Fruit>
:
var alimentList = new List<Aliment>(fruitList.Cast<Aliment>())
由于每个Fruit
是一个Aliment
,因此您可以将每个Aliment
转换为List<Aliment>
并使用它们来填充新的{{1} }。
如果这样做,您的Fruits
构造函数将编译:
public class Fruits : Aliments
{
public Fruits(List<Fruit> fruitList)
: base(new List<Aliment>(fruitList.Cast<Aliment>()))
{ }
}
我们不能做的是将List<Fruit>
转换为List<Aliment>
。
为什么?因为如果可以的话,我们可以这样做:
var alimentList = (List<Aliment>)fruitList;
alimentList.Add(new Vegetable());
这不会创建新列表-它只会将列表转换为其他类型。但是,如果我们可以将List<Fruit>
转换为List<Aliment>
,则可以将任何Aliment
添加到列表中,包括Vegetable
。这样我们的Vegetable
中将有一个List<Fruit>
。
这在我们前面并不总是很明显,但是编译器会立即发现并阻止它。
由于这个问题,如果使用上面显示的代码修复构造函数中的错误,您仍然会遇到完全相同的问题。 Fruits
仍将具有一个List<Aliment>
继承的Aliments
属性,因此您仍然可以这样做:
var fruits = new Fruits(someListOfFruit);
fruits.AlimentList.Add(new Vegetable());
这不会给您带来编译器错误,但显然仍然不是您想要的行为。
像这样的通用类可能会帮助您:
public abstract class Aliments<T> where T : Aliment
{
public Aliments(List<T> alimentList)
{
AlimentList = alimentList;
}
public List<T> AlimentList { get; private set; }
}
它允许您执行此操作。您可以定义一个继承自Aliments
但指定Aliment
实际类型的类。
public class Fruits : Aliments<Fruit>
{
public Fruits(List<Fruit> alimentList) : base(alimentList)
{
}
}
通过为通用参数Fruit
指定T
,您的AlimentList
属性现在定义为List<Fruit>
。编译器将只允许您向其中添加Fruit
。