Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.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#_Inheritance_Unity3d_Polymorphism_Abstract - Fatal编程技术网

C# 如何创建类的(多态性)集合/列表/数组,其中每个类可能具有一些不同的属性

C# 如何创建类的(多态性)集合/列表/数组,其中每个类可能具有一些不同的属性,c#,inheritance,unity3d,polymorphism,abstract,C#,Inheritance,Unity3d,Polymorphism,Abstract,如果我想为游戏创建汽车引擎设计,我将执行以下操作: 基类: public class EngineParts { public string name; public int ID; public GameObject Mesh; public Vector3 Position; public Quaternion Rotation; public string Description;

如果我想为游戏创建汽车引擎设计,我将执行以下操作:

基类:

public class EngineParts {
        public string name;
        public int ID; 
        public GameObject Mesh; 
        public Vector3 Position; 
        public Quaternion Rotation; 
        public string Description;
        public float new_value; // the brand new price of it
}
public class Rods : EngineParts
    {    
    }

public class Pistons : EngineParts
    {
        public float Size=51;
        public float Compression=51;
    }

public class Turbo : EngineParts
    {
        public float maxboostpressure;
        public float minboostpressure;
        public float MaxOperatingRPM;
        public float MinOperatingRPM;
        public float AirToEngineRatio;
        public float wasteGatePressure;
    }
然后我将拥有从中继承的类:

public class EngineParts {
        public string name;
        public int ID; 
        public GameObject Mesh; 
        public Vector3 Position; 
        public Quaternion Rotation; 
        public string Description;
        public float new_value; // the brand new price of it
}
public class Rods : EngineParts
    {    
    }

public class Pistons : EngineParts
    {
        public float Size=51;
        public float Compression=51;
    }

public class Turbo : EngineParts
    {
        public float maxboostpressure;
        public float minboostpressure;
        public float MaxOperatingRPM;
        public float MinOperatingRPM;
        public float AirToEngineRatio;
        public float wasteGatePressure;
    }
这里需要说明的是,所有汽车零件都共享一些通用值,这些值位于基本类中,即名称、ID、网格、位置和旋转。。等

它们还有其他更适合零件本身的值,例如涡轮增压器有maxboostpressure,它决定涡轮增压器可以处理的最大增压压力

现在在实际的游戏中,我需要能够将这些部件作为一个集合来使用

public EngineParts[] Part = new EngineParts[3];

Part[0] = new Rods();
Part[1] = new Pistons();
Part[2] = new Turbo();
因此,我可以在需要时遍历所有零件,因为它们都属于EngineParts类型

但是,当尝试为max maxboostpressure赋值时,我无法做到这一点

   //Note: Part[1] here is pistons
    Part[1].name = "SportPiston"; // this will work since it is type of EngineParts
    Part[1].maxboostpressure = 5.0; // this will not work
这是因为它是EngineParts类型

不过,我可以说:

Rods rd = new Rods();
Pistons pt = new Pistons();
Turbo tb = new Turbo();

pt.name = 5; // this will work
pt.maxboostpressure = 5; // this will work
现在,它们确实共享来自基类的相同数据,但我不能将棒、活塞、涡轮放在一个集合中,以循环或将它们传递到一个对所有这些都有效的函数中

所以

这里的问题是

我怎样才能最好地做到这一点?
1-将发动机的所有零件放在一个集合/列表中
2-能够在每个单独类型的零件上存储额外的数据,并且编码最少。

我一直在读关于
抽象类、重载、多态性和继承来解决这个问题,但仍然有一些我必须理解的东西,因此如果有人能为我指出正确的方向,我将不胜感激


提前感谢您

问题是,您如何知道列表中的第三项是特定的子类

您目前知道,因为您在数组中专门为它分配了一个位置,但是您应该这样做,因为在任何时候,任何子类都可以位于数组中的任何位置

考虑到这一点,您需要检查数组项的类型,然后在处理它之前强制转换它

if(Part[1] is Turbo)
{
   ((Turbo)Part[1]).maxboostpressure = 5;
}
有几种方法可以测试该类型:

typeof
采用类型名称(在编译时指定)

GetType
获取实例的运行时类型

is
如果实例位于继承树中,则返回true。

您可以使用“is”和“as”运算符

var list = new List<EngineParts>();

// add some parts to the list here...

foreach(var part in list) {
  if(part is Turbo) {
    (part as Turbo).maxboostpressure = 123;
  }
}
var list=newlist();
//在此列表中添加一些部分。。。
foreach(列表中的var部分){
如果(部件为涡轮增压器){
(部件为涡轮增压器)。最大增压压力=123;
}
}
试试这样的演员阵容:

Piston p = Part[1] as Piston;
如果零件[1]不是活塞,p将为空

然后继续

if(p!=null)
    doSomethingHere;

最好的方法是将数组分为几个子类。使用linq

EngineParts[] Part = new EngineParts[3];

Part[0] = new Rods();
Part[1] = new Pistons();
Part[2] = new Turbo();

Rods[] rods = Part.Where(x => x is Rods).Cast<Rods>().ToArray();
Pistons[] position = Part.Where(x => x is Pistons).Cast<Pistons>().ToArray();
Turbo[] turbo = Part.Where(x => x is Turbo).Cast<Turbo>().ToArray();

Turbo[0].name = "SportPiston"; 
Turbo[0].maxboostpressure = 5.0;
EngineParts[]部分=新的EngineParts[3];
第[0]部分=新杆();
第[1]部分=新活塞();
第[2]部分=新Turbo();
杆[]杆=零件,其中(x=>x为杆)。Cast().ToArray();
活塞[]位置=零件。其中(x=>x为活塞)。铸造()。ToArray();
Turbo[]Turbo=Part.Where(x=>x是Turbo.Cast().ToArray();
Turbo[0]。name=“Sport活塞”;
涡轮[0]。最大增压压力=5.0;
您将有3个已知类型的独立数组。现在您可以单独使用它们

请注意,索引不再像以前那样。所以,如果您不想这样做,为什么不为它们创建单独的数组呢?;)

没有副本等

var lst = new List<EngineParts>(); //fill it
foreach(var itm in lst.Where(x => x is Piston).Cast<Piston>())
{
    itm.maxboostpressure = 42;
}
var lst=newlist()//填满它
foreach(在lst.Where(x=>x是活塞).Cast()中的变量itm)
{
itm.maxboostpressure=42;
}

确实不需要检查两次类型。将
用作
一次,并检查其是否为空。请注意,此处的
将分别检查类型。不幸的是,编译器无法为您执行此操作,因为所有值都已装箱到基类,并且编译器无法通过查看数组的索引自动取消装箱。这应该像给定的答案一样在运行时完成。这非常有效,非常感谢您的友好回答。@AliT,嗨,我很高兴读到,这可以帮助您!由于您是SO新手,请注意,这里给出答案的专业人士渴望获得声誉积分。如果你能投票选出有帮助的答案,那将是非常感谢的。如果一个答案帮助你解决了你的问题,你应该把它标记为被接受的答案,这将向其他人表明,这个问题已经解决了。谢谢@Shnugo谢谢你的帮助,我将你的答案标记为已接受,并投票通过,谢谢你告诉我,什么是信誉点对tho有好处?让你感到高兴相信我xD@AliT@M.kazemAkhgary嗨,投你的票让你高兴;-)