在C#中传递派生对象的集合

时间:2012-11-26 20:35:30

标签: c# inheritance collections

我还在用OO和C#弄湿我的脚。我确信这是一个简单的问题,我想我知道答案,但我想确定。

如果我有一个名为Car的类,另一个名为Ford的类继承自Car,另一个名为Mustang的类继承自Ford }类。

是否可以创建接受Car个对象集合的方法,然后当我调用该方法时,实际上将Mustang(或Ford的集合传递给该方法)对象,因为它们实际上是Car个对象?

我的想法是,这应该是可能的,理解我只能访问Car类的Properties \ Methods。我是不是基于这个?

此外,如果我是对的,您可以这样做:您是否需要在调用方法时将Mustang集合转换为Car集合?

4 个答案:

答案 0 :(得分:3)

不,那是不可能的。

因此,如果我们有一个接受List<Car>类型的函数。显然,该功能应该能够在该列表中添加Prius,不是吗?好吧,如果您被允许将List<Mustang>传递给此方法,那么您刚刚将Prius添加到List<Mustang>,显然这很糟糕。

现在,如果该方法的参数为List或某些其他只读集合类型,而不是传递IEnumerable,那么它可能是“协变”。在这种情况下,作为示例,您可以接受IEnumerable<Car>并将其传递给List<Mustang>,因为您永远不会添加到列表中,您只能访问各种元素,并且只要Mustang个对象是Car个对象,这不是问题。

设计似乎有点......关闭。我不认为Ford应该继承CarFord不是汽车,而是品牌,公司,汽车类型。 Mustang 汽车,因此从一个汽车继承是有道理的。我会创建一个新类型,比如Manufacturer,您可以创建FordToyota等,并将其设为{只读} Car的属性。

答案 1 :(得分:1)

如果您只想访问Car课程中的方法和属性,则没有理由传递Mustangs列表。相反,您应该只是处理Mustangs,就好像它们是Cars一样。这是继承的主要要点之一。您只需创建一个类型为car List<Car>的列表,然后将Mustangs添加到其中。然后传递类型Car的列表。这是更具可扩展性的,因为它可以接受任何继承自Car的对象,并且因为您只使用Car中的属性/方法,所以它与您需要的定义一样严格。

如果您想在Mustang类中使用特定行为,但是用于调用该行为的公共接口在Car中定义方法,则在Mustang中覆盖它。同样,这更具可扩展性,因为当您创建NineEleven类时,您还可以覆盖此方法,从而在子类中提供不同的行为,而不会实际暴露其类型。

答案 2 :(得分:1)

其他人已经解释了将Mustangs集合作为参数发送到不同方法的各个方面,然后我将添加一些您可能会觉得有用的信息。

如果您有一系列汽车List<Car>,您只能通过以下方式获取野马:

IEnumerable<Mustang> mstngs = cars.OfType<Mustang>();
List<Mustang> mstngsLst = mstngs.ToList();

如果你有一系列Mustangs List<Mustang>,你可以将它们全部投入汽车:

IEnumerable<Car> cars = mstngs.Cast<Car>();
List<Car> carsLst = cars.ToList();

顺便说一下,转换回列表不是必须的。这取决于你需要对集合做什么。

答案 3 :(得分:0)

您可以执行此操作,传递包含List<Car>:s的Ford,例如:

public void Test()
{
    // This works:
    var fords = new List<Car> {new Ford()};
    FixCars(fords);

    // This does not work (since you cannot pass non car-typed list):
    // var mustangs = new List<Ford> {new Ford()};
    // FixCars(fords);
}

public void FixCars(List<Car> cars)
{
    // Do stuff, for example check actual type and do specialized things:
    foreach (var car in cars)
    {
        var ford = car as Ford;
        if (ford != null)
            ford.Honk();
    }
}

public class Car 
{    
}

public class Ford : Car
{
    public void Honk() {}
}