Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#-用于保存从同一基类继承的多个对象类型的列表_C#_List_Oop - Fatal编程技术网

C#-用于保存从同一基类继承的多个对象类型的列表

C#-用于保存从同一基类继承的多个对象类型的列表,c#,list,oop,C#,List,Oop,在下面的示例中,我希望能够将StandardCar或RaceCar的实例放入CarCollection列表中,然后在循环CarCollection列表时将它们转换为正确的数据类型 我知道这在C#中是不可能的。但是我找不到一种不涉及一个类的方法,该类在一个类中具有所有属性。既然NumberOfRaces只适用于赛车,那么这样做看起来有点混乱吗 当我在收集中循环时,我就会知道我是在使用标准车还是赛车。但目前,使用下面的代码,如果我将StandardCar放入列表中,然后循环该列表并将其转换为Stan

在下面的示例中,我希望能够将StandardCar或RaceCar的实例放入CarCollection列表中,然后在循环CarCollection列表时将它们转换为正确的数据类型

我知道这在C#中是不可能的。但是我找不到一种不涉及一个类的方法,该类在一个类中具有所有属性。既然NumberOfRaces只适用于赛车,那么这样做看起来有点混乱吗

当我在收集中循环时,我就会知道我是在使用标准车还是赛车。但目前,使用下面的代码,如果我将StandardCar放入列表中,然后循环该列表并将其转换为StandardCar,我将得到一个转换异常

请注意,我实际的最后一堂课比下面的要复杂得多

class Car
{
    public string Name {get; set;}
}

class RaceCar : Car
{
    public int NumberOfRaces {get; set;}
}

class StandardCar: Car
{
    public bool ChildrenInCar {get; set;}
}    

class CarCollection
{
   List<Car> Collection {get; set;}
}
等级车
{
公共字符串名称{get;set;}
}
级别赛车:赛车
{
公共int NumberOfRaces{get;set;}
}
等级标准车:汽车
{
公共bool childreneinvo{get;set;}
}    
分类收集
{
列表集合{get;set;}
}
感谢您的帮助。

创建一个界面:

public interface ICar{
//Place all common property / method definitions here
}
public class Car : ICar
{
//implementation
}
使Car实现该接口:

public interface ICar{
//Place all common property / method definitions here
}
public class Car : ICar
{
//implementation
}
然后更改您的汽车收藏:

public class CarCollection
{
List<ICar> Collection{get; set;}
}
公共类CarCollection
{
列表集合{get;set;}
}
现在,您应该能够将任何具有汽车底座的内容添加到该列表中。枚举集合时,所有ICAR都将在界面中定义这些属性/方法,您无需强制转换和类型检查即可访问这些属性/方法。

创建一个界面:

public interface ICar{
//Place all common property / method definitions here
}
public class Car : ICar
{
//implementation
}
使Car实现该接口:

public interface ICar{
//Place all common property / method definitions here
}
public class Car : ICar
{
//implementation
}
然后更改您的汽车收藏:

public class CarCollection
{
List<ICar> Collection{get; set;}
}
公共类CarCollection
{
列表集合{get;set;}
}

现在,您应该能够将任何具有汽车底座的内容添加到该列表中。枚举集合时,所有ICAR都将在界面中定义这些属性/方法,您可以访问这些属性/方法,而无需强制转换和类型检查。

是的,您可以将
StandardCar
添加到
List
集合中。您不能做的是在迭代集合时轻松访问派生类特定的属性

var collection = new CarCollection();
collection.Collection= new List<Car>();

collection.Collection.Add(new RaceCar());
collection.Collection.Add(new StandardCar());

foreach (var car in collection.Collection)
    Console.WriteLine(car.Name);

由于
childreneinbo
仅存在于
StandardCar
是,您可以将
StandardCar
添加到
列表
集合中。您不能做的是在迭代集合时轻松访问派生类特定的属性

var collection = new CarCollection();
collection.Collection= new List<Car>();

collection.Collection.Add(new RaceCar());
collection.Collection.Add(new StandardCar());

foreach (var car in collection.Collection)
    Console.WriteLine(car.Name);

由于
childreneinbo
仅存在于
StandardCar

中,因此完全可以正常添加到列表中,但要返回,需要测试返回的汽车类型:

// Create the cars
RaceCar rcar = new RaceCar();
StandardCar scar = new StandardCar();

// Add to the collection
CarCollection col = new CarCollection();
col.Add(rcar);
col.Add(scar);

// Iterate
foreach(Car car in col.Collection)
{
    if(car is RaceCar)
    {
        RaceCar racecar = (RaceCar)car;
    }
    else if(car is StandardCar)
    {
        StandardCar standCar = (StandardCar)car;
    }

    // ... etc
}
你也可以这样做:

car as RaceCar
并确保返回的值不为null


注意:代码未经测试,但应能正常工作。

完全有可能,您可以正常添加到列表中,但要返回,需要测试返回的车辆类型:

// Create the cars
RaceCar rcar = new RaceCar();
StandardCar scar = new StandardCar();

// Add to the collection
CarCollection col = new CarCollection();
col.Add(rcar);
col.Add(scar);

// Iterate
foreach(Car car in col.Collection)
{
    if(car is RaceCar)
    {
        RaceCar racecar = (RaceCar)car;
    }
    else if(car is StandardCar)
    {
        StandardCar standCar = (StandardCar)car;
    }

    // ... etc
}
你也可以这样做:

car as RaceCar
并确保返回的值不为null


注意:代码未经测试,但应该可以工作。

您可以检测强制转换是否工作:

List<Car> Collection;

..

foreach (Car car in Collection)
{
    RaceCar raceCar = car as RaceCar;
    if (raceCar != null)
    {
       raceCar.NumberOfRaces++;
    }
}

然后RaceCar会有自己的Update()实现,它会处理NumberOfRaces。此外,您可能不需要NumberOfRaces属性来设置一个setter,甚至可能不需要将其公开。

您可以检测强制转换是否有效:

List<Car> Collection;

..

foreach (Car car in Collection)
{
    RaceCar raceCar = car as RaceCar;
    if (raceCar != null)
    {
       raceCar.NumberOfRaces++;
    }
}

然后RaceCar会有自己的Update()实现,它会处理NumberOfRaces。此外,您可能不需要NumberOfRaces属性具有setter,甚至可能不需要将其公开。

处理此问题的方法多种多样。只要有可能,你应该尽量避免铸造的需要。例如,如果要以不同的方式显示不同的车辆,请覆盖
ToString
方法。您还可以添加以不同方式响应不同情况的方法。在基类中将这些方法声明为抽象的(同时也将基类声明为抽象的)

另一种可能性是测试实际类型:

if (car is RaceCar) {
    ((RaceCar)car).NumberOfRaces++;
} else if (car is StandardCar) {
    ((StandardCar)car).ChildrenInCar = 0;
}
另一种可能性是过滤车型并单独处理:

var raceCars = cars.OfType<RaceCar>();
foreach (raceCar in raceCars) {
   raceCar.NumberOfRaces++;
}
var raceCars=cars.OfType();
foreach(赛车中的赛车){
赛车。NumberOfRaces++;
}

处理此问题有不同的可能性。只要有可能,你应该尽量避免铸造的需要。例如,如果要以不同的方式显示不同的车辆,请覆盖
ToString
方法。您还可以添加以不同方式响应不同情况的方法。在基类中将这些方法声明为抽象的(同时也将基类声明为抽象的)

另一种可能性是测试实际类型:

if (car is RaceCar) {
    ((RaceCar)car).NumberOfRaces++;
} else if (car is StandardCar) {
    ((StandardCar)car).ChildrenInCar = 0;
}
另一种可能性是过滤车型并单独处理:

var raceCars = cars.OfType<RaceCar>();
foreach (raceCar in raceCars) {
   raceCar.NumberOfRaces++;
}
var raceCars=cars.OfType();
foreach(赛车中的赛车){
赛车。NumberOfRaces++;
}

另一种设计是使用接口指定不同汽车对象的不同逻辑边界

interface ICar ...
interface IRacingCar : ICar
interface IFlyingCar : ICar
interface IFamilyCar : ICar
然后在你的循环中,你根据各种汽车的逻辑能力对它们进行操作

void ProcessCars()
{
    foreach( var car in cars )
    {
         if(car is IRacingCar) ...
         if(car is IFlyingCar) ...
         if(car is IFamilyCar) ...
    }
}    
这种方法的优点是,您可以拥有更多类型的类,而不必为每个类都使用if语句。此外,您的if语句一次只需要处理一个问题

class RaceCar: IRacingCar ...
class FlyingRaceCar: IRaceCar, IFlyingCar ...
class FlyingFamilyCar: IFlyingCar, IFamilyCar ...
这个循环并不关心一辆车可以实现多个接口。它一次只需要处理一个问题

例如,任何一辆汽车都可以应对重力和空中交通管制,而不管它是否有儿童乘客或完成了多少场比赛


这就是接口的优点。它们允许界面的使用者只关心对象的质量。

另一种设计是使用界面指定不同汽车对象的不同逻辑边界

interface ICar ...
interface IRacingCar : ICar
interface IFlyingCar : ICar
interface IFamilyCar : ICar
然后在您的循环中对var进行操作